source: trunk/GSASIIpwdGUI.py @ 1349

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

small fixes to SASD plotting & GUI & tutorials

  • Property svn:eol-style set to native
  • Property svn:keywords set to Date Author Revision URL Id
File size: 181.0 KB
Line 
1# -*- coding: utf-8 -*-
2#GSASIIpwdGUI - powder data display routines
3########### SVN repository information ###################
4# $Date: 2014-05-15 15:45:46 +0000 (Thu, 15 May 2014) $
5# $Author: vondreele $
6# $Revision: 1349 $
7# $URL: trunk/GSASIIpwdGUI.py $
8# $Id: GSASIIpwdGUI.py 1349 2014-05-15 15:45:46Z 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: 1349 $")
32import GSASIImath as G2mth
33import GSASIIpwd as G2pwd
34import GSASIIIO as G2IO
35import GSASIIlattice as G2lat
36import GSASIIspc as G2spc
37import GSASIIindex as G2indx
38import GSASIIplot as G2plt
39import GSASIIgrid as G2gd
40import GSASIIElemGUI as G2elemGUI
41import GSASIIElem as G2elem
42import GSASIIsasd as G2sasd
43VERY_LIGHT_GREY = wx.Colour(235,235,235)
44WACV = wx.ALIGN_CENTER_VERTICAL
45Pwr10 = unichr(0x0b9)+unichr(0x0b0)
46Pwr20 = unichr(0x0b2)+unichr(0x0b0)
47Pwrm1 = unichr(0x207b)+unichr(0x0b9)
48Pwrm2 = unichr(0x207b)+unichr(0x0b2)
49Pwrm4 = unichr(0x207b)+unichr(0x2074)   #really -d but looks like -4 as a superscript
50# trig functions in degrees
51sind = lambda x: math.sin(x*math.pi/180.)
52tand = lambda x: math.tan(x*math.pi/180.)
53cosd = lambda x: math.cos(x*math.pi/180.)
54asind = lambda x: 180.*math.asin(x)/math.pi
55   
56def IsHistogramInAnyPhase(G2frame,histoName):
57    'Needs a doc string'
58    phases = G2gd.GetPatternTreeItemId(G2frame,G2frame.root,'Phases')
59    if phases:
60        item, cookie = G2frame.PatternTree.GetFirstChild(phases)
61        while item:
62            data = G2frame.PatternTree.GetItemPyData(item)
63            histoList = data['Histograms'].keys()
64            if histoName in histoList:
65                return True
66            item, cookie = G2frame.PatternTree.GetNextChild(phases, cookie)
67        return False
68    else:
69        return False
70
71def SetDefaultSample():
72    'Fills in default items for the Sample dictionary'
73    return {
74        'InstrName':'',
75        'ranId':ran.randint(0,sys.maxint),
76        'Scale':[1.0,True],'Type':'Debye-Scherrer','Absorption':[0.0,False],
77        'DisplaceX':[0.0,False],'DisplaceY':[0.0,False],'Diffuse':[],
78        'Temperature':300.,'Pressure':0.1,
79        'FreePrm1':0.,'FreePrm2':0.,'FreePrm3':0.,
80        'Gonio. radius':200.0,
81        'Omega':0.0,'Chi':0.0,'Phi':0.0,
82#SASD items
83        'Materials':[{'Name':'vacuum','VolFrac':1.0,},{'Name':'vacuum','VolFrac':0.0,}],
84        'Thick':1.0,'Contrast':[0.0,0.0],       #contrast & anomalous contrast
85        'Trans':1.0,                            #measured transmission
86        'SlitLen':0.0,                          #Slit length - in Q(A-1)
87        }
88def SetupSampleLabels(histName,dataType):
89    '''Setup a list of labels and number formatting for use in
90    labeling sample parameters.
91    :param str histName: Name of histogram, ("PWDR ...")
92    :param str dataType:
93    '''
94    parms = []
95    parms.append(['Scale','Histogram scale factor: ',[10,4]])
96    parms.append(['Gonio. radius','Goniometer radius (mm): ',[10,3]])
97    if 'PWDR' in histName:
98        if dataType == 'Debye-Scherrer':
99            parms += [['DisplaceX',u'Sample X displ. perp. to beam (\xb5m): ',[10,3]],
100                ['DisplaceY',u'Sample Y displ. || to beam (\xb5m): ',[10,3]],
101                ['Absorption',u'Sample absorption (\xb5\xb7r): ',[10,4]],]
102        elif dataType == 'Bragg-Brentano':
103            parms += [['Shift',u'Sample displacement(\xb5m): ',[10,4]],
104                ['Transparency',u'Sample transparency(1/\xb5eff, cm): ',[10,3]],
105                ['SurfRoughA','Surface roughness A: ',[10,4]],
106                ['SurfRoughB','Surface roughness B: ',[10,4]]]
107    elif 'SASD' in histName:
108        parms.append(['Thick','Sample thickness (mm)',[10,3]])
109        parms.append(['Trans','Transmission (meas)',[10,3]])
110        parms.append(['SlitLen',u'Slit length (Q,\xc5'+Pwrm1+')',[10,3]])
111    parms.append(['Omega','Goniometer omega:',[10,3]])
112    parms.append(['Chi','Goniometer chi:',[10,3]])
113    parms.append(['Phi','Goniometer phi:',[10,3]])
114    parms.append(['Temperature','Sample temperature (K): ',[10,3]])
115    parms.append(['Pressure','Sample pressure (MPa): ',[10,3]])
116    return parms
117
118def SetDefaultSASDModel():
119    'Fills in default items for the SASD Models dictionary'   
120    return {'Back':[0.0,False],'Size':{'MinDiam':50,'MaxDiam':10000,'Nbins':100,'logBins':True,'Method':'MaxEnt','Distribution':[],
121        'Shape':['Spheroid',1.0],'MaxEnt':{'Niter':100,'Precision':0.01,'Sky':-3},
122        'IPG':{'Niter':100,'Approach':0.8,'Power':-1},'Reg':{},},           
123        'Particle':{'Matrix':{'Name':'vacuum','VolFrac':[0.0,False]},'Levels':[],},
124        'Current':'Size dist.','BackFile':'',
125        }
126       
127def SetDefaultSubstances():
128    'Fills in default items for the SASD Substances dictionary'
129    return {'Substances':{'vacuum':{'Elements':{},'Volume':1.0,'Density':0.0,'Scatt density':0.0}}}
130
131def GetHistsLikeSelected(G2frame):
132    '''Get the histograms that match the current selected one:
133    The histogram prefix and data type (PXC etc.), the number of
134    wavelengths and the instrument geometry (Debye-Scherrer etc.)
135    must all match. The current histogram is not included in the list.
136
137    :param wx.Frame G2frame: pointer to main GSAS-II data tree
138    '''
139    histList = []
140    inst,inst2 = G2frame.PatternTree.GetItemPyData(
141        G2gd.GetPatternTreeItemId(
142            G2frame,G2frame.PatternId, 'Instrument Parameters')
143        )
144    hType = inst['Type'][0]
145    if 'Lam1' in inst:
146        hLam = 2
147    elif 'Lam' in inst:
148        hLam = 1
149    else:
150        hLam = 0
151    sample = G2frame.PatternTree.GetItemPyData(
152        G2gd.GetPatternTreeItemId(
153            G2frame,G2frame.PatternId, 'Sample Parameters')
154        )
155    hGeom = sample.get('Type')
156    hstName = G2frame.PatternTree.GetItemText(G2frame.PatternId)
157    hPrefix = hstName.split()[0]+' '
158    # cycle through tree looking for items that match the above
159    item, cookie = G2frame.PatternTree.GetFirstChild(G2frame.root)       
160    while item:
161        name = G2frame.PatternTree.GetItemText(item)
162        if name.startswith(hPrefix) and name != hstName:
163            cGeom,cType,cLam, = '?','?',-1
164            subitem, subcookie = G2frame.PatternTree.GetFirstChild(item)
165            while subitem:
166                subname = G2frame.PatternTree.GetItemText(subitem)
167                if subname == 'Sample Parameters':
168                    sample = G2frame.PatternTree.GetItemPyData(subitem)
169                    cGeom = sample.get('Type')
170                elif subname == 'Instrument Parameters':
171                    inst,inst2 = G2frame.PatternTree.GetItemPyData(subitem)
172                    cType = inst['Type'][0]
173                    if 'Lam1' in inst:
174                        cLam = 2
175                    elif 'Lam' in inst:
176                        cLam = 1
177                    else:
178                        cLam = 0
179                subitem, subcookie = G2frame.PatternTree.GetNextChild(item, subcookie)
180            if cLam == hLam and cType == hType and cGeom == hGeom:
181                if name not in histList: histList.append(name)
182        item, cookie = G2frame.PatternTree.GetNextChild(G2frame.root, cookie)
183    return histList
184
185def SetCopyNames(histName,dataType,addNames=[]):
186    '''Determine the items in the sample parameters that should be copied,
187    depending on the histogram type and the instrument type.
188    '''
189    copyNames = ['Scale',]
190    histType = 'HKLF'
191    if 'PWDR' in histName:
192        histType = 'PWDR'
193        if 'Debye' in dataType:
194            copyNames += ['DisplaceX','DisplaceY','Absorption']
195        else:       #Bragg-Brentano
196            copyNames += ['Shift','Transparency','SurfRoughA','SurfRoughB']
197    elif 'SASD' in histName:
198        histType = 'SASD'
199        copyNames += ['Materials','Thick',]
200    if len(addNames):
201        copyNames += addNames
202    return histType,copyNames
203
204def CopySelectedHistItems(G2frame):
205    '''Global copy: Copy items from current histogram to others.
206    This is called from the menubar and is available only when the top histogram tree entry
207    is selected.
208    '''
209    hst = G2frame.PatternTree.GetItemText(G2frame.PatternId)
210    histList = GetHistsLikeSelected(G2frame)
211    if not histList:
212        G2frame.ErrorDialog('No match','No histograms match '+hst,G2frame.dataFrame)
213        return
214    choices = ['Limits','Background','Instrument Parameters','Sample Parameters']
215    dlg = G2gd.G2MultiChoiceDialog(
216        G2frame.dataFrame, 
217        'Copy which histogram sections from\n'+str(hst[5:]),
218        'Select copy sections', choices, filterBox=False)
219    dlg.SetSelections(range(len(choices)))
220    choiceList = []
221    if dlg.ShowModal() == wx.ID_OK:
222        choiceList = [choices[i] for i in dlg.GetSelections()]
223    if not choiceList: return
224   
225    dlg = G2gd.G2MultiChoiceDialog(
226        G2frame.dataFrame, 
227        'Copy parameters from\n'+str(hst[5:])+' to...',
228        'Copy parameters', histList)
229    results = []
230    try:
231        if dlg.ShowModal() == wx.ID_OK:
232            results = dlg.GetSelections()
233    finally:
234        dlg.Destroy()
235    copyList = []
236    for i in results: 
237        copyList.append(histList[i])
238
239    if 'Limits' in choiceList: # Limits
240        data = G2frame.PatternTree.GetItemPyData(
241            G2gd.GetPatternTreeItemId(G2frame,G2frame.PatternId,'Limits'))
242        for item in copyList:
243            Id = G2gd.GetPatternTreeItemId(G2frame,G2frame.root,item)
244            G2frame.PatternTree.SetItemPyData(
245                G2gd.GetPatternTreeItemId(G2frame,Id,'Limits'),
246                copy.deepcopy(data))
247    if 'Background' in choiceList:  # Background
248        data = G2frame.PatternTree.GetItemPyData(
249            G2gd.GetPatternTreeItemId(G2frame,G2frame.PatternId,'Background'))
250        for item in copyList:
251            Id = G2gd.GetPatternTreeItemId(G2frame,G2frame.root,item)
252            G2frame.PatternTree.SetItemPyData(
253                G2gd.GetPatternTreeItemId(G2frame,Id,'Background'),
254                copy.deepcopy(data))
255    if 'Instrument Parameters' in choiceList:  # Instrument Parameters
256        # for now all items in Inst. parms are copied
257        data,data1 = G2frame.PatternTree.GetItemPyData(
258            G2gd.GetPatternTreeItemId(
259                G2frame,G2frame.PatternId,'Instrument Parameters'))
260        for item in copyList:
261            Id = G2gd.GetPatternTreeItemId(G2frame,G2frame.root,item)
262            G2frame.PatternTree.GetItemPyData(
263                G2gd.GetPatternTreeItemId(G2frame,Id,'Instrument Parameters')
264                )[0].update(copy.deepcopy(data))
265            G2frame.PatternTree.GetItemPyData(
266                G2gd.GetPatternTreeItemId(G2frame,Id,'Instrument Parameters')
267                )[1].update(copy.deepcopy(data1))
268    if 'Sample Parameters' in choiceList:  # Sample Parameters
269        data = G2frame.PatternTree.GetItemPyData(
270            G2gd.GetPatternTreeItemId(
271                G2frame,G2frame.PatternId,'Sample Parameters'))
272        # selects items to be copied
273        histType,copyNames = SetCopyNames(hst,data['Type'],
274            addNames = ['Omega','Chi','Phi','Gonio. radius','InstrName'])
275        copyDict = {parm:data[parm] for parm in copyNames}
276        for item in copyList:
277            Id = G2gd.GetPatternTreeItemId(G2frame,G2frame.root,item)
278            G2frame.PatternTree.GetItemPyData(
279                G2gd.GetPatternTreeItemId(G2frame,Id,'Sample Parameters')
280                ).update(copy.deepcopy(copyDict))
281                         
282################################################################################
283#####  Powder Peaks
284################################################################################           
285       
286def UpdatePeakGrid(G2frame, data):
287    '''respond to selection of PWDR powder peaks data tree item.
288    '''
289    if G2frame.dataDisplay:
290        G2frame.dataFrame.Clear()
291       
292    def OnAutoSearch(event):
293        PatternId = G2frame.PatternId
294        PickId = G2frame.PickId
295        limits = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId, 'Limits'))[1]
296        inst,inst2 = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId, 'Instrument Parameters'))
297        profile = G2frame.PatternTree.GetItemPyData(PatternId)[1]
298        x0 = profile[0]
299        iBeg = np.searchsorted(x0,limits[0])
300        iFin = np.searchsorted(x0,limits[1])
301        x = x0[iBeg:iFin]
302        y0 = profile[1][iBeg:iFin]
303        y1 = copy.copy(y0)
304        ysig = np.std(y1)
305        offset = [-1,1]
306        ymask = ma.array(y0,mask=(y0<ysig))
307        for off in offset:
308            ymask = ma.array(ymask,mask=(ymask-np.roll(y0,off)<=0.))
309        indx = ymask.nonzero()
310        mags = ymask[indx]
311        poss = x[indx]
312        refs = zip(poss,mags)
313        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        G2plt.PlotPatterns(G2frame,plotType='SASD',newPlot=True)
1403        UpdateSampleGrid(G2frame,data)       
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        G2plt.PlotPatterns(G2frame,plotType='SASD',newPlot=False)
1487
1488    def OnSampleFlagCopy(event):
1489        histType,copyNames = SetCopyNames(histName,data['Type'])
1490        flagDict = {}
1491        for parm in copyNames:
1492            flagDict[parm] = data[parm][1]
1493        hst = G2frame.PatternTree.GetItemText(G2frame.PatternId)
1494        histList = GetHistsLikeSelected(G2frame)
1495        if not histList:
1496            G2frame.ErrorDialog('No match','No histograms match '+hst,G2frame.dataFrame)
1497            return
1498        dlg = G2gd.G2MultiChoiceDialog(
1499            G2frame.dataFrame, 
1500            'Copy sample ref. flags from\n'+str(hst[5:])+' to...',
1501            'Copy sample flags', histList)
1502        try:
1503            if dlg.ShowModal() == wx.ID_OK:
1504                result = dlg.GetSelections()
1505                for i in result: 
1506                    item = histList[i]
1507                    Id = G2gd.GetPatternTreeItemId(G2frame,G2frame.root,item)
1508                    sampleData = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,Id,'Sample Parameters'))
1509                    for name in copyNames:
1510                        sampleData[name][1] = copy.copy(flagDict[name])
1511        finally:
1512            dlg.Destroy()
1513
1514    def OnHistoType(event):
1515        Obj = event.GetEventObject()
1516        data['Type'] = Obj.GetValue()
1517        if data['Type'] == 'Bragg-Brentano' and 'Shift' not in data:    #set up defaults for new type(s)
1518            data['Shift'] = [0.0,False]
1519            data['Transparency'] = [0.0,False]
1520        wx.CallAfter(UpdateSampleGrid,G2frame,data)
1521       
1522    def SetNameVal():
1523        inst = instNameVal.GetValue()
1524        data['InstrName'] = inst.strip()
1525
1526    def OnNameVal(event):
1527        event.Skip()
1528        wx.CallAfter(SetNameVal)
1529       
1530    def AfterChange(invalid,value,tc):
1531        if invalid:
1532            return
1533        if tc.key == 0 and 'SASD' in histName:          #a kluge for Scale!
1534            G2plt.PlotPatterns(G2frame,plotType='SASD',newPlot=True)
1535        elif tc.key == 'Thick':
1536            wx.CallAfter(UpdateSampleGrid,G2frame,data)           
1537           
1538    def OnMaterial(event):
1539        Obj = event.GetEventObject()
1540        id,key = Info[Obj.GetId()]
1541        if key == 'Name':
1542            data['Materials'][id][key] = Obj.GetValue()
1543        elif key == 'VolFrac':
1544            try:
1545                value = min(max(0.,float(Obj.GetValue())),1.)
1546            except ValueError:
1547                value = data['Materials'][id][key]
1548            data['Materials'][id][key] = value
1549            data['Materials'][not id][key] = 1.-value
1550        wx.CallAfter(UpdateSampleGrid,G2frame,data)
1551
1552    ######## DEBUG #######################################################
1553    #import GSASIIpwdGUI
1554    #reload(GSASIIpwdGUI)
1555    #reload(G2gd)
1556    ######################################################################
1557    histName = G2frame.PatternTree.GetItemText(G2frame.PatternId)
1558    if G2frame.dataDisplay:
1559        G2frame.dataFrame.Clear()
1560    G2gd.SetDataMenuBar(G2frame,G2frame.dataFrame.SampleMenu)
1561    G2frame.dataFrame.SetLabel('Sample Parameters')
1562    G2frame.Bind(wx.EVT_MENU, OnSetScale, id=G2gd.wxID_SETSCALE)
1563    G2frame.Bind(wx.EVT_MENU, OnSampleCopy, id=G2gd.wxID_SAMPLECOPY)
1564    G2frame.Bind(wx.EVT_MENU, OnSampleCopySelected, id=G2gd.wxID_SAMPLECOPYSOME)
1565    G2frame.Bind(wx.EVT_MENU, OnSampleFlagCopy, id=G2gd.wxID_SAMPLEFLAGCOPY)
1566    G2frame.Bind(wx.EVT_MENU, OnSampleSave, id=G2gd.wxID_SAMPLESAVE)
1567    G2frame.Bind(wx.EVT_MENU, OnSampleLoad, id=G2gd.wxID_SAMPLELOAD)
1568    if 'SASD' in histName:
1569        G2frame.dataFrame.SetScale.Enable(True)
1570    if not G2frame.dataFrame.GetStatusBar():
1571        Status = G2frame.dataFrame.CreateStatusBar()   
1572    G2frame.dataDisplay = wx.Panel(G2frame.dataFrame)
1573    Controls = G2frame.PatternTree.GetItemPyData(
1574        G2gd.GetPatternTreeItemId(G2frame,G2frame.root, 'Controls'))
1575#patch
1576    if 'ranId' not in data:
1577        data['ranId'] = ran.randint(0,sys.maxint)
1578    if not 'Gonio. radius' in data:
1579        data['Gonio. radius'] = 200.0
1580    if not 'Omega' in data:
1581        data.update({'Omega':0.0,'Chi':0.0,'Phi':0.0})
1582    if type(data['Temperature']) is int:
1583        data['Temperature'] = float(data['Temperature'])
1584    if 'FreePrm1' not in Controls:
1585        Controls['FreePrm1'] = 'Sample humidity (%)'
1586    if 'FreePrm2' not in Controls:
1587        Controls['FreePrm2'] = 'Sample voltage (V)'
1588    if 'FreePrm3' not in Controls:
1589        Controls['FreePrm3'] = 'Applied load (MN)'
1590    if 'FreePrm1' not in data:
1591        data['FreePrm1'] = 0.
1592    if 'FreePrm2' not in data:
1593        data['FreePrm2'] = 0.
1594    if 'FreePrm3' not in data:
1595        data['FreePrm3'] = 0.
1596    if 'SurfRoughA' not in data and 'PWDR' in histName:
1597        data['SurfRoughA'] = [0.,False]
1598        data['SurfRoughB'] = [0.,False]
1599    if 'Trans' not in data and 'SASD' in histName:
1600        data['Trans'] = 1.0
1601    if 'SlitLen' not in data and 'SASD' in histName:
1602        data['SlitLen'] = 0.0
1603#patch end
1604   
1605    parms = SetupSampleLabels(histName,data.get('Type'))
1606    mainSizer = wx.BoxSizer(wx.VERTICAL)
1607    topSizer = wx.BoxSizer(wx.HORIZONTAL)
1608    topSizer.Add((-1,-1),1,wx.EXPAND,1)
1609    topSizer.Add(wx.StaticText(G2frame.dataDisplay,label='Sample and Experimental Parameters'))
1610    topSizer.Add((-1,-1),1,wx.EXPAND,1)
1611    mainSizer.Add(topSizer,0,wx.EXPAND,1)
1612    nameSizer = wx.BoxSizer(wx.HORIZONTAL)
1613    nameSizer.Add(wx.StaticText(G2frame.dataDisplay,wx.ID_ANY,' Instrument Name'),
1614                0,WACV)
1615    nameSizer.Add((-1,-1),1,wx.EXPAND,1)
1616    instNameVal = wx.TextCtrl(G2frame.dataDisplay,wx.ID_ANY,data.get('InstrName',''),
1617                              size=(200,-1),style=wx.TE_PROCESS_ENTER)       
1618    nameSizer.Add(instNameVal)
1619    instNameVal.Bind(wx.EVT_CHAR,OnNameVal)
1620    mainSizer.Add(nameSizer,0,wx.EXPAND,1)
1621    mainSizer.Add((5,5),0)
1622
1623    if 'PWDR' in histName:
1624        nameSizer = wx.BoxSizer(wx.HORIZONTAL)
1625        nameSizer.Add(wx.StaticText(G2frame.dataDisplay,wx.ID_ANY,' Diffractometer type: '),
1626                    0,WACV)
1627        choices = ['Debye-Scherrer','Bragg-Brentano',]
1628        histoType = wx.ComboBox(G2frame.dataDisplay,wx.ID_ANY,value=data['Type'],choices=choices,
1629            style=wx.CB_READONLY|wx.CB_DROPDOWN)
1630        histoType.Bind(wx.EVT_COMBOBOX, OnHistoType)
1631        nameSizer.Add(histoType)
1632        mainSizer.Add(nameSizer,0,wx.EXPAND,1)
1633        mainSizer.Add((5,5),0)
1634
1635    parmSizer = wx.FlexGridSizer(10,2,5,0)
1636    for key,lbl,nDig in parms:
1637        if 'list' in str(type(data[key])):
1638            parmRef = G2gd.G2CheckBox(G2frame.dataDisplay,' '+lbl,data[key],1)
1639            parmSizer.Add(parmRef,0,WACV|wx.EXPAND)
1640            parmVal = G2gd.ValidatedTxtCtrl(G2frame.dataDisplay,data[key],0,
1641                nDig=nDig,typeHint=float,OnLeave=AfterChange)
1642        else:
1643            parmSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' '+lbl),
1644                0,WACV|wx.EXPAND)
1645            parmVal = G2gd.ValidatedTxtCtrl(G2frame.dataDisplay,data,key,
1646                typeHint=float,OnLeave=AfterChange)
1647        parmSizer.Add(parmVal,1,wx.EXPAND)
1648    Info = {}
1649
1650       
1651    for key in ('FreePrm1','FreePrm2','FreePrm3'):
1652        parmVal = G2gd.ValidatedTxtCtrl(G2frame.dataDisplay,Controls,key,typeHint=str,
1653                                        notBlank=False)
1654        parmSizer.Add(parmVal,1,wx.EXPAND)
1655        parmVal = G2gd.ValidatedTxtCtrl(G2frame.dataDisplay,data,key,typeHint=float)
1656        parmSizer.Add(parmVal,1,wx.EXPAND)
1657    mainSizer.Add(parmSizer,1,wx.EXPAND)
1658    mainSizer.Add((0,5),0)   
1659    if 'SASD' in histName:
1660        rho = [0.,0.]
1661        anomrho = [0.,0.]
1662        mu = 0.
1663        subSizer = wx.FlexGridSizer(1,4,5,5)
1664        Substances = G2frame.PatternTree.GetItemPyData(
1665            G2gd.GetPatternTreeItemId(G2frame,G2frame.PatternId, 'Substances'))
1666        for id,item in enumerate(data['Materials']):
1667            subSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Material: '),0,WACV)
1668            matsel = wx.ComboBox(G2frame.dataDisplay,value=item['Name'],choices=Substances['Substances'].keys(),
1669                style=wx.CB_READONLY|wx.CB_DROPDOWN)
1670            Info[matsel.GetId()] = [id,'Name']
1671            matsel.Bind(wx.EVT_COMBOBOX,OnMaterial)       
1672            subSizer.Add(matsel,0,WACV)
1673            subSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Volume fraction: '),0,WACV)
1674            volfrac = wx.TextCtrl(G2frame.dataDisplay,value=str('%.3f'%(item['VolFrac'])),style=wx.TE_PROCESS_ENTER)
1675            Info[volfrac.GetId()] = [id,'VolFrac']
1676            volfrac.Bind(wx.EVT_TEXT_ENTER,OnMaterial)
1677            volfrac.Bind(wx.EVT_KILL_FOCUS,OnMaterial)
1678            subSizer.Add(volfrac,0,WACV)
1679            material = Substances['Substances'][item['Name']]
1680            mu += item['VolFrac']*material.get('XAbsorption',0.)
1681            rho[id] = material['Scatt density']
1682            anomrho[id] = material.get('XAnom density',0.)
1683        data['Contrast'] = [(rho[1]-rho[0])**2,(anomrho[1]-anomrho[0])**2]
1684        mainSizer.Add(subSizer,0)
1685        conSizer = wx.BoxSizer(wx.HORIZONTAL)
1686        conSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Contrast: %10.2f '%(data['Contrast'][0])),0,WACV)
1687        conSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Anom. Contrast: %10.2f '%(data['Contrast'][1])),0,WACV)
1688        mut =  mu*data['Thick']
1689        conSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Transmission (calc): %10.3f  '%(np.exp(-mut))),0,WACV)
1690        mainSizer.Add(conSizer,0)
1691   
1692    mainSizer.Layout()   
1693    G2frame.dataDisplay.SetSizer(mainSizer)
1694    Size = mainSizer.Fit(G2frame.dataFrame)
1695    G2frame.dataDisplay.SetSize(Size)
1696    G2frame.dataFrame.setSizePosLeft(Size)
1697               
1698################################################################################
1699#####  Indexing Peaks
1700################################################################################           
1701       
1702def UpdateIndexPeaksGrid(G2frame, data):
1703    '''respond to selection of PWDR Index Peak List data
1704    tree item.
1705    '''
1706    IndexId = G2gd.GetPatternTreeItemId(G2frame,G2frame.PatternId, 'Index Peak List')
1707    Inst = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,G2frame.PatternId, 'Instrument Parameters'))[0]
1708    wave = G2mth.getWave(Inst)
1709   
1710    def RefreshIndexPeaksGrid(event):
1711        r,c =  event.GetRow(),event.GetCol()
1712        data = G2frame.IndexPeaksTable.GetData()
1713        if c == 2:
1714            if data[r][c]:
1715                data[r][c] = False
1716            else:
1717                data[r][c] = True
1718            G2frame.IndexPeaksTable.SetData(data)
1719            G2frame.PatternTree.SetItemPyData(IndexId,data)
1720            G2frame.dataDisplay.ForceRefresh()
1721           
1722    def OnReload(event):
1723        data = []
1724        peaks = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,G2frame.PatternId, 'Peak List'))
1725        for peak in peaks:
1726            dsp = wave/(2.0*sind((peak[0]-Inst['Zero'][1])/2.0))
1727            data.append([peak[0],peak[2],True,False,0,0,0,dsp,0.0])
1728        G2frame.PatternTree.SetItemPyData(IndexId,data)
1729        UpdateIndexPeaksGrid(G2frame,data)
1730       
1731    def KeyEditPickGrid(event):
1732        colList = G2frame.dataDisplay.GetSelectedCols()
1733        rowList = G2frame.dataDisplay.GetSelectedRows()
1734        data = G2frame.PatternTree.GetItemPyData(IndexId)
1735        if event.GetKeyCode() == wx.WXK_RETURN:
1736            event.Skip(True)
1737        elif event.GetKeyCode() == wx.WXK_CONTROL:
1738            event.Skip(True)
1739        elif event.GetKeyCode() == wx.WXK_SHIFT:
1740            event.Skip(True)
1741        elif colList:
1742            G2frame.dataDisplay.ClearSelection()
1743            key = event.GetKeyCode()
1744            for col in colList:
1745                if G2frame.IndexPeaksTable.GetColLabelValue(col) in ['use','refine']:
1746                    if key == 89: #'Y'
1747                        for row in range(G2frame.IndexPeaksTable.GetNumberRows()): data[row][col]=True
1748                    elif key == 78:  #'N'
1749                        for row in range(G2frame.IndexPeaksTable.GetNumberRows()): data[row][col]=False
1750           
1751    if G2frame.dataDisplay:
1752        G2frame.dataFrame.Clear()
1753    if not G2frame.dataFrame.GetStatusBar():
1754        Status = G2frame.dataFrame.CreateStatusBar()
1755    if 'PWD' in G2frame.PatternTree.GetItemText(G2frame.PatternId):
1756        G2gd.SetDataMenuBar(G2frame,G2frame.dataFrame.IndPeaksMenu)
1757        G2frame.Bind(wx.EVT_MENU, OnReload, id=G2gd.wxID_INDXRELOAD)
1758    G2frame.dataFrame.IndexPeaks.Enable(False)
1759    G2frame.IndexPeaksTable = []
1760    if data:
1761        G2frame.dataFrame.IndexPeaks.Enable(True)
1762        cells = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,G2frame.PatternId, 'Unit Cells List'))
1763        if cells:
1764            cellist = cells[2]
1765            dmin = cells[3]
1766            G2frame.HKL = []
1767            for i,cell in enumerate(cellist):
1768                if cell[-1]:
1769                    ibrav = cell[2]
1770                    A = G2lat.cell2A(cell[3:9])
1771                    G2frame.HKL = G2lat.GenHBravais(dmin,ibrav,A)
1772                    G2indx.IndexPeaks(data,G2frame.HKL)
1773                    for hkl in G2frame.HKL:
1774                        hkl.append(2.0*asind(wave/(2.*hkl[3]))+Inst['Zero'][1])             
1775    rowLabels = []
1776    for i in range(len(data)): rowLabels.append(str(i+1))
1777    colLabels = ['position','intensity','use','indexed','h','k','l','d-obs','d-calc']
1778    Types = [wg.GRID_VALUE_FLOAT+':10,4',wg.GRID_VALUE_FLOAT+':10,1',wg.GRID_VALUE_BOOL,
1779        wg.GRID_VALUE_BOOL,wg.GRID_VALUE_LONG,wg.GRID_VALUE_LONG,wg.GRID_VALUE_LONG,
1780        wg.GRID_VALUE_FLOAT+':10,5',wg.GRID_VALUE_FLOAT+':10,5']
1781    G2frame.PatternTree.SetItemPyData(IndexId,data)
1782    G2frame.IndexPeaksTable = G2gd.Table(data,rowLabels=rowLabels,colLabels=colLabels,types=Types)
1783    G2frame.dataFrame.SetLabel('Index Peak List')
1784    G2frame.dataDisplay = G2gd.GSGrid(parent=G2frame.dataFrame)               
1785    G2frame.dataDisplay.SetTable(G2frame.IndexPeaksTable, True)
1786    for r in range(G2frame.dataDisplay.GetNumberRows()):
1787        for c in range(G2frame.dataDisplay.GetNumberCols()):
1788            if c == 2:
1789                G2frame.dataDisplay.SetReadOnly(r,c,isReadOnly=False)
1790            else:
1791                G2frame.dataDisplay.SetReadOnly(r,c,isReadOnly=True)
1792    G2frame.dataDisplay.Bind(wg.EVT_GRID_CELL_LEFT_CLICK, RefreshIndexPeaksGrid)
1793    G2frame.dataDisplay.Bind(wx.EVT_KEY_DOWN, KeyEditPickGrid)                 
1794    G2frame.dataDisplay.SetMargins(0,0)
1795    G2frame.dataDisplay.AutoSizeColumns(False)
1796    G2frame.dataFrame.setSizePosLeft([490,300])
1797 
1798################################################################################
1799#####  Unit cells
1800################################################################################           
1801       
1802def UpdateUnitCellsGrid(G2frame, data):
1803    '''respond to selection of PWDR Unit Cells data tree item.
1804    '''
1805    UnitCellsId = G2gd.GetPatternTreeItemId(G2frame,G2frame.PatternId, 'Unit Cells List')
1806    SPGlist = G2spc.spglist
1807    bravaisSymb = ['Fm3m','Im3m','Pm3m','R3-H','P6/mmm','I4/mmm',
1808        'P4/mmm','Fmmm','Immm','Cmmm','Pmmm','C2/m','P2/m','P1']
1809    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',
1810        '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']
1811    Inst = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,G2frame.PatternId, 'Instrument Parameters'))[0]
1812    wave = G2mth.getWave(Inst)
1813   
1814    def SetLattice(controls):
1815        ibrav = bravaisSymb.index(controls[5])
1816        if ibrav in [0,1,2]:
1817            controls[7] = controls[8] = controls[6]
1818            controls[9] = controls[10] = controls[11] = 90.
1819        elif ibrav in [3,4,5,6]:
1820            controls[7] = controls[6]
1821            controls[9] = controls[10] = controls[11] = 90.
1822            if ibrav in [3,4]:
1823                controls[11] = 120.
1824        elif ibrav in [7,8,9,10]:
1825            controls[9] = controls[10] = controls[11] = 90.
1826        elif ibrav in [11,12]:
1827            controls[9] = controls[11] = 90.  # b unique
1828        if len(controls) < 13: controls.append(0)
1829        controls[12] = G2lat.calc_V(G2lat.cell2A(controls[6:12]))
1830        return ibrav
1831       
1832    def OnNcNo(event):
1833        controls[2] = NcNo.GetValue()
1834       
1835    def OnStartVol(event):
1836        try:
1837            stVol = int(float(startVol.GetValue()))
1838            if stVol < 25:
1839                raise ValueError
1840        except ValueError:
1841            stVol = 25
1842        controls[3] = stVol
1843        startVol.SetValue("%d"%(stVol))
1844       
1845    def OnBravais(event):
1846        Obj = event.GetEventObject()
1847        bravais[bravList.index(Obj.GetId())] = Obj.GetValue()
1848       
1849    def OnZero(event):
1850        try:
1851            Zero = min(5.0,max(-5.0,float(zero.GetValue())))
1852        except ValueError:
1853            Zero = 0.0
1854        controls[1] = Zero
1855        zero.SetValue("%.4f"%(Zero))
1856       
1857    def OnZeroVar(event):
1858        controls[0] = zeroVar.GetValue()
1859       
1860    def OnBravSel(event):
1861        brav = bravSel.GetString(bravSel.GetSelection())
1862        controls[5] = brav
1863        controls[13] = SPGlist[brav][0]       
1864        wx.CallAfter(UpdateUnitCellsGrid,G2frame,data)
1865       
1866    def OnSpcSel(event):
1867        controls[13] = spcSel.GetString(spcSel.GetSelection())       
1868       
1869    def OnCellChange(event):
1870        ibrav = bravaisSymb.index(controls[5])
1871        Obj = event.GetEventObject()
1872        ObjId = cellList.index(Obj.GetId())
1873        try:
1874            value = max(1.0,float(Obj.GetValue()))
1875        except ValueError:
1876            if ObjId < 3:               #bad cell edge - reset
1877                value = controls[6+ObjId]
1878            else:                       #bad angle
1879                value = 90.
1880        if ibrav in [0,1,2]:
1881            controls[6] = controls[7] = controls[8] = value
1882            controls[9] = controls[10] = controls[11] = 90.0
1883            Obj.SetValue("%.5f"%(controls[6]))
1884        elif ibrav in [3,4,5,6]:
1885            if ObjId == 0:
1886                controls[6] = controls[7] = value
1887                Obj.SetValue("%.5f"%(controls[6]))
1888            else:
1889                controls[8] = value
1890                Obj.SetValue("%.5f"%(controls[8]))
1891            controls[9] = controls[10] = controls[11] = 90.0
1892            if ibrav in [3,4]:
1893                controls[11] = 120.
1894        elif ibrav in [7,8,9,10]:
1895            controls[6+ObjId] = value
1896            Obj.SetValue("%.5f"%(controls[6+ObjId]))
1897            controls[9] = controls[10] = controls[11] = 90.0
1898        elif ibrav in [11,12]:
1899            controls[9] = controls[11] = 90.0
1900            if ObjId != 3:
1901                controls[6+ObjId] = value
1902                Obj.SetValue("%.5f"%(controls[6+ObjId]))
1903            else:
1904                controls[10] = value
1905                Obj.SetValue("%.3f"%(controls[10]))
1906        else:
1907            controls[6+ObjId] = value
1908            if ObjId < 3:
1909                Obj.SetValue("%.5f"%(controls[6+ObjId]))
1910            else:
1911                Obj.SetValue("%.3f"%(controls[6+ObjId]))
1912        controls[12] = G2lat.calc_V(G2lat.cell2A(controls[6:12]))
1913        volVal.SetValue("%.3f"%(controls[12]))
1914       
1915    def OnHklShow(event):
1916        PatternId = G2frame.PatternId
1917        PickId = G2frame.PickId   
1918        limits = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId, 'Limits'))[1]
1919        controls,bravais,cells,dmin = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId, 'Unit Cells List'))
1920        cell = controls[6:12]
1921        A = G2lat.cell2A(cell)
1922        ibrav = bravaisSymb.index(controls[5])
1923        spc = controls[13]
1924        SGData = G2spc.SpcGroup(spc)[1]
1925        dmin = wave/(2.0*sind(limits[1]/2.0))
1926        G2frame.HKL = G2pwd.getHKLpeak(dmin,SGData,A)
1927        for hkl in G2frame.HKL:
1928            hkl.append(2.0*asind(wave/(2.*hkl[3]))+controls[1]+Inst['Zero'][1])             
1929        if 'PKS' in G2frame.PatternTree.GetItemText(G2frame.PatternId):
1930            G2plt.PlotPowderLines(G2frame)
1931        else:
1932            G2plt.PlotPatterns(G2frame)
1933           
1934    def OnSortCells(event):
1935        controls,bravais,cells,dmin = G2frame.PatternTree.GetItemPyData(UnitCellsId)
1936        c =  event.GetCol()
1937        if colLabels[c] == 'M20':
1938            cells = G2indx.sortM20(cells)
1939        elif colLabels[c] == 'Volume':
1940            cells = G2indx.sortVolume(cells)
1941        else:
1942            return
1943        data = [controls,bravais,cells,dmin]
1944        G2frame.PatternTree.SetItemPyData(UnitCellsId,data)
1945        wx.CallAfter(UpdateUnitCellsGrid,G2frame,data)
1946       
1947    def CopyUnitCell(event):
1948        controls,bravais,cells,dmin = G2frame.PatternTree.GetItemPyData(UnitCellsId)
1949        for Cell in cells:
1950            if Cell[-2]:
1951                break
1952        cell = Cell[2:9]
1953        controls[4] = 1
1954        controls[5] = bravaisSymb[cell[0]]
1955        controls[6:12] = cell[1:8]
1956        controls[12] = G2lat.calc_V(G2lat.cell2A(controls[6:12]))
1957        controls[13] = spaceGroups[bravaisSymb.index(controls[5])]
1958        G2frame.PatternTree.SetItemPyData(UnitCellsId,[controls,bravais,cells,dmin])
1959        G2frame.dataFrame.RefineCell.Enable(True)
1960        wx.CallAfter(UpdateUnitCellsGrid,G2frame,data)       
1961               
1962    def RefineCell(event):
1963        def cellPrint(ibrav,A):
1964            cell = G2lat.A2cell(A)
1965            Vol = G2lat.calc_V(A)
1966            if ibrav in [0,1,2]:
1967                print "%s%10.6f" % ('a =',cell[0])
1968            elif ibrav in [3,4,5,6]:
1969                print "%s%10.6f %s%10.6f %s%12.3f" % ('a =',cell[0],' c =',cell[2],' volume =',Vol)
1970            elif ibrav in [7,8,9,10]:
1971                print "%s%10.6f %s%10.6f %s%10.6f %s%12.3f" % ('a =',cell[0],'b =',cell[1],'c =',cell[2],' volume =',Vol)
1972            elif ibrav in [11,12]:
1973                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)
1974            else:
1975                print "%s%10.6f %s%10.6f %s%10.6f" % ('a =',cell[0],'b =',cell[1],'c =',cell[2])
1976                print "%s%8.3f %s%8.3f %s%8.3f %s%12.3f" % ('alpha =',cell[3],'beta =',cell[4],'gamma =',cell[5],' volume =',Vol)
1977             
1978        PatternId = G2frame.PatternId
1979        PickId = G2frame.PickId   
1980        peaks = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId, 'Index Peak List'))
1981        if not peaks:
1982            G2frame.ErrorDialog('No peaks!', 'Nothing to refine!')
1983            return       
1984        print 'Refine cell'
1985        controls,bravais,cells,dmin = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId, 'Unit Cells List'))
1986        cell = controls[6:12]
1987        A = G2lat.cell2A(cell)
1988        ibrav = bravaisSymb.index(controls[5])
1989        SGData = G2spc.SpcGroup(controls[13])[1]
1990        dmin = G2indx.getDmin(peaks)-0.005
1991        G2frame.HKL = G2pwd.getHKLpeak(dmin,SGData,A)
1992        G2indx.IndexPeaks(peaks,G2frame.HKL)
1993        Lhkl,M20,X20,Aref,Zero = G2indx.refinePeaksZ(peaks,wave,ibrav,A,controls[1],controls[0])           
1994        controls[1] = Zero
1995        controls[6:12] = G2lat.A2cell(Aref)
1996        controls[12] = G2lat.calc_V(Aref)
1997        data = [controls,bravais,cells,dmin]
1998        cells = G2frame.PatternTree.GetItemPyData(UnitCellsId)[2]
1999        for cell in cells:
2000            cell[-2] = False
2001        cells.insert(0,[M20,X20,ibrav]+controls[6:13]+[True,False])
2002        data[2] = cells
2003        G2frame.PatternTree.SetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId, 'Unit Cells List'),data)
2004        G2frame.HKL = G2lat.GenHBravais(dmin,ibrav,Aref)
2005        print "%s%10.3f" % ('refinement M20 = ',M20)
2006        print 'unindexed lines = ',X20
2007        cellPrint(ibrav,Aref)
2008        for hkl in G2frame.HKL:
2009            hkl.append(2.0*asind(wave/(2.*hkl[3]))+controls[1]+Inst['Zero'][1])             
2010        if 'PKS' in G2frame.PatternTree.GetItemText(G2frame.PatternId):
2011            G2plt.PlotPowderLines(G2frame)
2012        else:
2013            G2plt.PlotPatterns(G2frame)
2014        wx.CallAfter(UpdateUnitCellsGrid,G2frame,data)
2015       
2016    def IndexPeaks(event):
2017        PatternId = G2frame.PatternId   
2018        print 'Peak Indexing'
2019        keepcells = []
2020        try:
2021            controls,bravais,cells,dmin = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId, 'Unit Cells List'))
2022            for cell in cells:
2023                if cell[11]:
2024                    keepcells.append(cell)
2025        except IndexError:
2026            pass
2027        except ValueError:
2028            G2frame.ErrorDialog('Error','Need to set controls in Unit Cell List first')
2029            return
2030        if True not in bravais:
2031            G2frame.ErrorDialog('Error','No Bravais lattices selected')
2032            return
2033        G2frame.dataFrame.CopyCell.Enable(False)
2034        G2frame.dataFrame.RefineCell.Enable(False)
2035        OK,dmin,newcells = G2indx.DoIndexPeaks(peaks,wave,controls,bravais)
2036        cells = keepcells+newcells
2037        cells = G2indx.sortM20(cells)
2038        cells[0][10] = True
2039        if OK:
2040            data = [controls,bravais,cells,dmin]
2041            G2frame.PatternTree.SetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId, 'Unit Cells List'),data)
2042            bestCell = cells[0]
2043            if bestCell[0] > 10.:
2044                G2frame.HKL = G2lat.GenHBravais(dmin,bestCell[2],G2lat.cell2A(bestCell[3:9]))
2045                for hkl in G2frame.HKL:
2046                    hkl.append(2.0*asind(wave/(2.*hkl[3]))+controls[1]+Inst['Zero'][1])             
2047                if 'PKS' in G2frame.PatternTree.GetItemText(G2frame.PatternId):
2048                    G2plt.PlotPowderLines(G2frame)
2049                else:
2050                    G2plt.PlotPatterns(G2frame)
2051            G2frame.dataFrame.CopyCell.Enable(True)
2052            G2frame.dataFrame.IndexPeaks.Enable(True)
2053            G2frame.dataFrame.MakeNewPhase.Enable(True)
2054        wx.CallAfter(UpdateUnitCellsGrid,G2frame,data)
2055               
2056    def RefreshUnitCellsGrid(event):
2057        data =G2frame.PatternTree.GetItemPyData(UnitCellsId)
2058        cells,dmin = data[2:]
2059        r,c =  event.GetRow(),event.GetCol()
2060        if cells:
2061            if c == 2:
2062                for i in range(len(cells)):
2063                    cells[i][-2] = False
2064                    UnitCellsTable.SetValue(i,c,False)
2065                UnitCellsTable.SetValue(r,c,True)
2066                gridDisplay.ForceRefresh()
2067                cells[r][-2] = True
2068                ibrav = cells[r][2]
2069                A = G2lat.cell2A(cells[r][3:9])
2070                G2frame.HKL = G2lat.GenHBravais(dmin,ibrav,A)
2071                for hkl in G2frame.HKL:
2072                    hkl.append(2.0*asind(wave/(2.*hkl[3]))+controls[1]+Inst['Zero'][1])             
2073                if 'PKS' in G2frame.PatternTree.GetItemText(G2frame.PatternId):
2074                    G2plt.PlotPowderLines(G2frame)
2075                else:
2076                    G2plt.PlotPatterns(G2frame)
2077            elif c == 11:
2078                if UnitCellsTable.GetValue(r,c):
2079                    UnitCellsTable.SetValue(r,c,False)
2080                    cells[r][c] = False
2081                else:
2082                    cells[r][c] = True
2083                    UnitCellsTable.SetValue(r,c,True)
2084                gridDisplay.ForceRefresh()
2085            G2frame.PatternTree.SetItemPyData(UnitCellsId,data)               
2086       
2087    def MakeNewPhase(event):
2088        if not G2gd.GetPatternTreeItemId(G2frame,G2frame.root,'Phases'):
2089            sub = G2frame.PatternTree.AppendItem(parent=G2frame.root,text='Phases')
2090        else:
2091            sub = G2gd.GetPatternTreeItemId(G2frame,G2frame.root,'Phases')
2092        PhaseName = ''
2093        dlg = wx.TextEntryDialog(None,'Enter a name for this phase','Phase Name Entry','New phase',
2094            style=wx.OK)
2095        try:
2096            if dlg.ShowModal() == wx.ID_OK:
2097                PhaseName = dlg.GetValue()
2098                cells = G2frame.PatternTree.GetItemPyData(UnitCellsId)[2]
2099                for Cell in cells:
2100                    if Cell[-2]:
2101                        break
2102                cell = Cell[2:10]       
2103                sub = G2frame.PatternTree.AppendItem(parent=sub,text=PhaseName)
2104                E,SGData = G2spc.SpcGroup(controls[13])
2105                G2frame.PatternTree.SetItemPyData(sub, \
2106                    G2IO.SetNewPhase(Name=PhaseName,SGData=SGData,cell=cell[1:]))
2107                Status.SetStatusText('Change space group from '+str(controls[13])+' if needed')
2108        finally:
2109            dlg.Destroy()
2110           
2111    if G2frame.dataDisplay:
2112        G2frame.dataFrame.Clear()
2113    G2gd.SetDataMenuBar(G2frame,G2frame.dataFrame.IndexMenu)
2114    if not G2frame.dataFrame.GetStatusBar():
2115        Status = G2frame.dataFrame.CreateStatusBar()
2116    G2frame.Bind(wx.EVT_MENU, IndexPeaks, id=G2gd.wxID_INDEXPEAKS)
2117    G2frame.Bind(wx.EVT_MENU, CopyUnitCell, id=G2gd.wxID_COPYCELL)
2118    G2frame.Bind(wx.EVT_MENU, RefineCell, id=G2gd.wxID_REFINECELL)
2119    G2frame.Bind(wx.EVT_MENU, MakeNewPhase, id=G2gd.wxID_MAKENEWPHASE)
2120   
2121    controls,bravais,cells,dmin = data
2122    if len(controls) < 13:              #add cell volume if missing
2123        controls.append(G2lat.calc_V(G2lat.cell2A(controls[6:12])))
2124    if len(controls) < 14:              #add space gropu used in indexing
2125        controls.append(spaceGroups[bravaisSymb.index(controls[5])])
2126    G2frame.PatternTree.SetItemPyData(UnitCellsId,data)            #update with volume
2127    bravaisNames = ['Cubic-F','Cubic-I','Cubic-P','Trigonal-R','Trigonal/Hexagonal-P',
2128        'Tetragonal-I','Tetragonal-P','Orthorhombic-F','Orthorhombic-I','Orthorhombic-C',
2129        'Orthorhombic-P','Monoclinic-C','Monoclinic-P','Triclinic']
2130    cellGUIlist = [[[0,1,2],4,zip([" Unit cell: a = "," Vol = "],["%.5f","%.3f"],[True,False],[0,0])],
2131    [[3,4,5,6],6,zip([" Unit cell: a = "," c = "," Vol = "],["%.5f","%.5f","%.3f"],[True,True,False],[0,2,0])],
2132    [[7,8,9,10],8,zip([" Unit cell: a = "," b = "," c = "," Vol = "],["%.5f","%.5f","%.5f","%.3f"],
2133        [True,True,True,False],[0,1,2,0])],
2134    [[11,12],10,zip([" Unit cell: a = "," b = "," c = "," beta = "," Vol = "],
2135        ["%.5f","%.5f","%.5f","%.3f","%.3f"],[True,True,True,True,False],[0,1,2,4,0])],
2136    [[13,],8,zip([" Unit cell: a = "," b = "," c = "," Vol = "," alpha = "," beta = "," gamma = "],
2137        ["%.5f","%.5f","%.5f","%.3f","%.3f","%.3f","%.3f"],
2138        [True,True,True,False,True,True,True],[0,1,2,0,3,4,5])]]
2139   
2140    G2frame.dataFrame.SetLabel('Unit Cells List')
2141    G2frame.sp = wx.SplitterWindow(G2frame.dataFrame)
2142    G2frame.dataDisplay = wx.Panel(G2frame.sp, style=wx.SUNKEN_BORDER)
2143    G2frame.dataFrame.IndexPeaks.Enable(False)
2144    peaks = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,G2frame.PatternId, 'Index Peak List'))
2145    if peaks:
2146        G2frame.dataFrame.IndexPeaks.Enable(True)
2147    G2frame.dataFrame.RefineCell.Enable(False)
2148    if controls[12] > 1.0:                               #if a "real" volume (i.e. not default)
2149        G2frame.dataFrame.RefineCell.Enable(True)   
2150    G2frame.dataFrame.CopyCell.Enable(False)
2151    G2frame.dataFrame.MakeNewPhase.Enable(False)       
2152    if cells:
2153        G2frame.bottom = wx.Panel(G2frame.sp, style=wx.SUNKEN_BORDER)
2154        G2frame.sp.SplitHorizontally(G2frame.dataDisplay,G2frame.bottom,0)
2155        G2frame.dataFrame.CopyCell.Enable(True)
2156        G2frame.dataFrame.MakeNewPhase.Enable(True)       
2157    mainSizer = wx.BoxSizer(wx.VERTICAL)
2158    mainSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' Indexing controls: '),0,WACV)
2159    mainSizer.Add((5,5),0)
2160    littleSizer = wx.FlexGridSizer(2,5,5,5)
2161    littleSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' Max Nc/Nobs '),0,WACV)
2162    NcNo = wx.SpinCtrl(G2frame.dataDisplay)
2163    NcNo.SetRange(1,6)
2164    NcNo.SetValue(controls[2])
2165    NcNo.Bind(wx.EVT_SPINCTRL,OnNcNo)
2166    littleSizer.Add(NcNo,0,WACV)
2167    littleSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' Start Volume '),0,WACV)
2168    startVol = wx.TextCtrl(G2frame.dataDisplay,value=str('%d'%(controls[3])),style=wx.TE_PROCESS_ENTER)
2169    startVol.Bind(wx.EVT_TEXT_ENTER,OnStartVol)
2170    startVol.Bind(wx.EVT_KILL_FOCUS,OnStartVol)
2171    littleSizer.Add(startVol,0,WACV)
2172    mainSizer.Add(littleSizer,0)
2173    mainSizer.Add((5,5),0)
2174    mainSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Select Bravais Lattices for indexing: '),
2175        0,WACV)
2176    mainSizer.Add((5,5),0)
2177    littleSizer = wx.FlexGridSizer(2,7,5,5)
2178    bravList = []
2179    bravs = zip(bravais,bravaisNames)
2180    for brav,bravName in bravs:
2181        bravCk = wx.CheckBox(G2frame.dataDisplay,label=bravName)
2182        bravList.append(bravCk.GetId())
2183        bravCk.SetValue(brav)
2184        bravCk.Bind(wx.EVT_CHECKBOX,OnBravais)
2185        littleSizer.Add(bravCk,0,WACV)
2186    mainSizer.Add(littleSizer,0)
2187    mainSizer.Add((5,5),0)
2188   
2189    mainSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' Cell Refinement: '),0,WACV)
2190    mainSizer.Add((5,5),0)
2191    littleSizer = wx.BoxSizer(wx.HORIZONTAL)
2192    littleSizer.Add(wx.StaticText(G2frame.dataDisplay,label=" Bravais lattice "),0,WACV)
2193    bravSel = wx.Choice(G2frame.dataDisplay,choices=bravaisSymb)
2194    bravSel.SetSelection(bravaisSymb.index(controls[5]))
2195    bravSel.Bind(wx.EVT_CHOICE,OnBravSel)
2196    littleSizer.Add(bravSel,0,WACV)
2197    littleSizer.Add(wx.StaticText(G2frame.dataDisplay,label=" Space group "),0,WACV)
2198    spcSel = wx.Choice(G2frame.dataDisplay,choices=SPGlist[controls[5]])
2199    spcSel.SetSelection(SPGlist[controls[5]].index(controls[13]))
2200    spcSel.Bind(wx.EVT_CHOICE,OnSpcSel)
2201    littleSizer.Add(spcSel,0,WACV)
2202    littleSizer.Add(wx.StaticText(G2frame.dataDisplay,label=" Zero offset"),0,WACV)
2203    zero = wx.TextCtrl(G2frame.dataDisplay,value="%.4f"%(controls[1]),style=wx.TE_PROCESS_ENTER)
2204    zero.Bind(wx.EVT_TEXT_ENTER,OnZero)
2205    zero.Bind(wx.EVT_KILL_FOCUS,OnZero)
2206    littleSizer.Add(zero,0,WACV)
2207    zeroVar = wx.CheckBox(G2frame.dataDisplay,label="Refine?")
2208    zeroVar.SetValue(controls[0])
2209    zeroVar.Bind(wx.EVT_CHECKBOX,OnZeroVar)
2210    littleSizer.Add(zeroVar,0,WACV)
2211    hklShow = wx.Button(G2frame.dataDisplay,label="Show hkl positions")
2212    hklShow.Bind(wx.EVT_BUTTON,OnHklShow)
2213    littleSizer.Add(hklShow,0,WACV)
2214    mainSizer.Add(littleSizer,0)
2215   
2216    mainSizer.Add((5,5),0)
2217    ibrav = SetLattice(controls)
2218    for cellGUI in cellGUIlist:
2219        if ibrav in cellGUI[0]:
2220            useGUI = cellGUI
2221    cellList = []
2222    littleSizer = wx.FlexGridSizer(2,useGUI[1],5,5)
2223    for txt,fmt,ifEdit,Id in useGUI[2]:
2224        littleSizer.Add(wx.StaticText(G2frame.dataDisplay,label=txt),0,WACV)
2225        if ifEdit:          #a,b,c,etc.
2226            cellVal = wx.TextCtrl(G2frame.dataDisplay,value=(fmt%(controls[6+Id])),style=wx.TE_PROCESS_ENTER)
2227            cellVal.Bind(wx.EVT_TEXT_ENTER,OnCellChange)       
2228            cellVal.Bind(wx.EVT_KILL_FOCUS,OnCellChange)
2229            littleSizer.Add(cellVal,0,WACV)
2230            cellList.append(cellVal.GetId())
2231        else:               #volume
2232            volVal = wx.TextCtrl(G2frame.dataDisplay,value=(fmt%(controls[12])),style=wx.TE_READONLY)
2233            volVal.SetBackgroundColour(VERY_LIGHT_GREY)
2234            littleSizer.Add(volVal,0,WACV)
2235    mainSizer.Add(littleSizer,0)
2236       
2237    mainSizer.Layout()   
2238    G2frame.dataDisplay.SetSizer(mainSizer)
2239    topSize = mainSizer.Fit(G2frame.dataFrame)
2240    G2frame.dataDisplay.SetSize(topSize)
2241    if cells:
2242        if ibrav == 13:
2243            topSize[1] += 230
2244        else:
2245            topSize[1] += 200
2246    G2frame.dataFrame.setSizePosLeft(topSize)   
2247   
2248    if cells:
2249        bottomSize = topSize        #screwy but bottom doesn't have a size in linux!
2250        bottomSize[0] -= 20         #to reveal slider
2251        if ibrav == 13:
2252            bottomSize[1] -= 240
2253        else:
2254            bottomSize[1] -= 210
2255        wx.StaticText(parent=G2frame.bottom,label=' Indexing Result ')
2256        rowLabels = []
2257        colLabels = ['M20','X20','use','Bravais','a','b','c','alpha','beta','gamma','Volume','Keep']
2258        Types = [wg.GRID_VALUE_FLOAT+':10,2',wg.GRID_VALUE_NUMBER,wg.GRID_VALUE_BOOL,wg.GRID_VALUE_STRING,]+ \
2259            3*[wg.GRID_VALUE_FLOAT+':10,5',]+3*[wg.GRID_VALUE_FLOAT+':10,3',]+ \
2260            [wg.GRID_VALUE_FLOAT+':10,2',wg.GRID_VALUE_BOOL]
2261        numRows = len(cells)
2262        table = []
2263        for cell in cells:
2264            rowLabels.append('')
2265            row = cell[0:2]+[cell[-2]]+[bravaisSymb[cell[2]]]+cell[3:10]+[cell[11],]
2266            if cell[-2]:
2267                A = G2lat.cell2A(cell[3:9])
2268                G2frame.HKL = G2lat.GenHBravais(dmin,cell[2],A)
2269                for hkl in G2frame.HKL:
2270                    hkl.append(2.0*asind(wave/(2.*hkl[3]))+controls[1]+Inst['Zero'][1])             
2271            table.append(row)
2272        UnitCellsTable = G2gd.Table(table,rowLabels=rowLabels,colLabels=colLabels,types=Types)
2273        gridDisplay = G2gd.GSGrid(G2frame.bottom)
2274        gridDisplay.SetPosition(wx.Point(0,20))               
2275        gridDisplay.SetTable(UnitCellsTable, True)
2276        G2frame.dataFrame.CopyCell.Enable(True)
2277        gridDisplay.Bind(wg.EVT_GRID_CELL_LEFT_CLICK,RefreshUnitCellsGrid)
2278        gridDisplay.Bind(wg.EVT_GRID_LABEL_LEFT_DCLICK,OnSortCells)
2279        gridDisplay.SetMargins(0,0)
2280        gridDisplay.SetRowLabelSize(0)
2281        gridDisplay.AutoSizeColumns(False)
2282        for r in range(gridDisplay.GetNumberRows()):
2283            for c in range(gridDisplay.GetNumberCols()):
2284                if c == 2:
2285                    gridDisplay.SetReadOnly(r,c,isReadOnly=False)
2286                else:
2287                    gridDisplay.SetReadOnly(r,c,isReadOnly=True)
2288        gridDisplay.SetSize(bottomSize)
2289
2290################################################################################
2291#####  Reflection list
2292################################################################################           
2293       
2294def UpdateReflectionGrid(G2frame,data,HKLF=False,Name=''):
2295    '''respond to selection of PWDR Reflections data tree item.
2296    '''
2297    if not data:
2298        print 'No phases, no reflections'
2299        return
2300    if HKLF:
2301        G2frame.RefList = 1
2302        phaseName = Name
2303    else:
2304        phaseName = G2frame.RefList
2305        phases = data.keys()
2306   
2307        def OnSelectPhase(event):
2308            dlg = wx.SingleChoiceDialog(G2frame,'Select','Phase',phases)
2309            try:
2310                if dlg.ShowModal() == wx.ID_OK:
2311                    sel = dlg.GetSelection()
2312                    G2frame.RefList = phases[sel]
2313                    UpdateReflectionGrid(G2frame,data)
2314            finally:
2315                dlg.Destroy()
2316            G2plt.PlotPatterns(G2frame)
2317           
2318        def OnPlotHKL(event):
2319            FoMax = np.max(refList.T[8])
2320            controls = {'Type' : 'Fo','ifFc' : True,     
2321                'HKLmax' : [int(np.max(refList.T[0])),int(np.max(refList.T[1])),int(np.max(refList.T[2]))],
2322                'HKLmin' : [int(np.min(refList.T[0])),int(np.min(refList.T[1])),int(np.min(refList.T[2]))],
2323                'FoMax' : FoMax,'Zone' : '001','Layer' : 0,'Scale' : 1.0,}
2324            G2plt.PlotSngl(G2frame,newPlot=True,Data=controls,hklRef=refList,Title=phaseName)
2325       
2326    if G2frame.dataDisplay:
2327        G2frame.dataFrame.Clear()
2328    rowLabels = []
2329    if HKLF:
2330        G2gd.SetDataMenuBar(G2frame)
2331        refs = data[1]['RefList']
2332    else:       
2333        G2gd.SetDataMenuBar(G2frame,G2frame.dataFrame.ReflMenu)
2334        if not G2frame.dataFrame.GetStatusBar():
2335            Status = G2frame.dataFrame.CreateStatusBar()   
2336        G2frame.Bind(wx.EVT_MENU, OnSelectPhase, id=G2gd.wxID_SELECTPHASE)
2337        G2frame.Bind(wx.EVT_MENU, OnPlotHKL, id=G2gd.wxID_PWDHKLPLOT)   #not work yet
2338        G2frame.dataFrame.SelectPhase.Enable(False)
2339        if len(data) > 1:
2340            G2frame.dataFrame.SelectPhase.Enable(True)
2341        try:            #patch for old reflection lists
2342            refList = np.array(data[G2frame.RefList]['RefList'])
2343            I100 = refList.T[8]*refList.T[11]
2344        except TypeError:
2345            refList = np.array([refl[:11] for refl in data[G2frame.RefList]])
2346            I100 = refList.T[8]*np.array([refl[13] for refl in data[G2frame.RefList]])
2347        Imax = np.max(I100)
2348        if Imax:
2349            I100 *= 100.0/Imax
2350        refs = np.vstack((refList.T[:11],I100)).T
2351    for i in range(len(refs)): rowLabels.append(str(i))
2352    if HKLF:
2353        colLabels = ['H','K','L','mul','d','Fosq','sig','Fcsq','FoTsq','FcTsq','phase',]
2354    else:
2355        colLabels = ['H','K','L','mul','d','pos','sig','gam','Fosq','Fcsq','phase','I100',]
2356    Types = 4*[wg.GRID_VALUE_LONG,]+4*[wg.GRID_VALUE_FLOAT+':10,4',]+ \
2357        2*[wg.GRID_VALUE_FLOAT+':10,2',]+[wg.GRID_VALUE_FLOAT+':10,3',]+ \
2358        [wg.GRID_VALUE_FLOAT+':10,2',]
2359    G2frame.PeakTable = G2gd.Table(refs,rowLabels=rowLabels,colLabels=colLabels,types=Types)
2360    G2frame.dataFrame.SetLabel('Reflection List for '+phaseName)
2361    G2frame.dataDisplay = G2gd.GSGrid(parent=G2frame.dataFrame)
2362    G2frame.dataDisplay.SetTable(G2frame.PeakTable, True)
2363    G2frame.dataDisplay.EnableEditing(False)
2364    G2frame.dataDisplay.SetMargins(0,0)
2365    G2frame.dataDisplay.AutoSizeColumns(False)
2366    G2frame.dataDisplay.Fit()
2367    size = G2frame.dataDisplay.GetSize()
2368    G2frame.dataFrame.setSizePosLeft([size[0]+32,350])
2369   
2370################################################################################
2371#####  SASD Substances
2372################################################################################
2373           
2374def UpdateSubstanceGrid(G2frame,data):
2375    '''respond to selection of SASD Substance data tree item.
2376    '''
2377    import Substances as substFile
2378   
2379    def OnLoadSubstance(event):
2380        names = substFile.Substances.keys()
2381        names.sort()
2382        dlg = wx.SingleChoiceDialog(G2frame, 'Which substance?', 'Select substance', names, wx.CHOICEDLG_STYLE)
2383        try:
2384            if dlg.ShowModal() == wx.ID_OK:
2385                name = names[dlg.GetSelection()]
2386            else:
2387                return
2388        finally:
2389            dlg.Destroy()
2390        data['Substances'][name] = {'Elements':{},'Volume':1.0,'Density':1.0,
2391            'Scatt density':0.0,'XAnom density':0.0,'XAbsorption':0.0}
2392        subst = substFile.Substances[name]
2393        ElList = subst['Elements'].keys()
2394        for El in ElList:
2395            Info = G2elem.GetAtomInfo(El.strip().upper())
2396            Info.update(subst['Elements'][El])
2397            data['Substances'][name]['Elements'][El] = Info
2398            if 'Volume' in subst:
2399                data['Substances'][name]['Volume'] = subst['Volume']
2400                data['Substances'][name]['Density'] = \
2401                    G2mth.Vol2Den(data['Substances'][name]['Elements'],data['Substances'][name]['Volume'])
2402            elif 'Density' in subst:
2403                data['Substances'][name]['Density'] = subst['Density']
2404                data['Substances'][name]['Volume'] = \
2405                    G2mth.Den2Vol(data['Substances'][name]['Elements'],data['Substances'][name]['Density'])
2406            else:
2407                data['Substances'][name]['Volume'] = G2mth.El2EstVol(data['Substances'][name]['Elements'])
2408                data['Substances'][name]['Density'] = \
2409                    G2mth.Vol2Den(data['Substances'][name]['Elements'],data['Substances'][name]['Volume'])
2410            data['Substances'][name]['Scatt density'] = \
2411                G2mth.XScattDen(data['Substances'][name]['Elements'],data['Substances'][name]['Volume'])[0]
2412            contrst,absorb = G2mth.XScattDen(data['Substances'][name]['Elements'],data['Substances'][name]['Volume'],wave)         
2413            data['Substances'][name]['XAnom density'] = contrst
2414            data['Substances'][name]['XAbsorption'] = absorb
2415                         
2416        UpdateSubstanceGrid(G2frame,data)
2417       
2418    def OnCopySubstance(event):
2419        hst = G2frame.PatternTree.GetItemText(G2frame.PatternId)
2420        histList = GetHistsLikeSelected(G2frame)
2421        if not histList:
2422            G2frame.ErrorDialog('No match','No histograms match '+hst,G2frame.dataFrame)
2423            return
2424        copyList = []
2425        dlg = G2gd.G2MultiChoiceDialog(
2426            G2frame.dataFrame, 
2427            'Copy substances from\n'+hst[5:]+' to...',
2428            'Copy substances', histList)
2429        try:
2430            if dlg.ShowModal() == wx.ID_OK:
2431                for i in dlg.GetSelections(): 
2432                    copyList.append(histList[i])
2433        finally:
2434            dlg.Destroy()       
2435        for item in copyList:
2436            Id = G2gd.GetPatternTreeItemId(G2frame,G2frame.root,item)
2437            G2frame.PatternTree.SetItemPyData(G2gd.GetPatternTreeItemId(G2frame,Id,'Substances'),
2438                copy.copy(data))
2439   
2440    def OnAddSubstance(event):
2441        dlg = wx.TextEntryDialog(None,'Enter a name for this substance','Substance Name Entry','New substance',
2442            style=wx.OK)
2443        if dlg.ShowModal() == wx.ID_OK:
2444            Name = dlg.GetValue()
2445            data['Substances'][Name] = {'Elements':{},'Volume':1.0,'Density':1.0,
2446                'Scatt density':0.0,'XAnom density':0.,'XAbsorption':0.}
2447        dlg.Destroy()
2448        AddElement(Name)
2449        UpdateSubstanceGrid(G2frame,data)
2450       
2451    def OnDeleteSubstance(event):
2452        TextList = []
2453        for name in data['Substances']:
2454            if name != 'vacuum':
2455                TextList += [name,]
2456        if not TextList:
2457            return
2458        dlg = wx.SingleChoiceDialog(G2frame, 'Which substance?', 'Select substance to delete', TextList, wx.CHOICEDLG_STYLE)
2459        try:
2460            if dlg.ShowModal() == wx.ID_OK:
2461                name = TextList[dlg.GetSelection()]
2462            else:
2463                return
2464        finally:
2465            dlg.Destroy()
2466        del(data['Substances'][name])
2467        UpdateSubstanceGrid(G2frame,data)       
2468               
2469    def OnAddElement(event):       
2470        TextList = []
2471        for name in data['Substances']:
2472            if name != 'vacuum':
2473                TextList += [name,]
2474        if not TextList:
2475            return
2476        dlg = wx.SingleChoiceDialog(G2frame, 'Which substance?', 'Select substance', TextList, wx.CHOICEDLG_STYLE)
2477        try:
2478            if dlg.ShowModal() == wx.ID_OK:
2479                name = TextList[dlg.GetSelection()]
2480            else:
2481                return
2482        finally:
2483            dlg.Destroy()
2484        AddElement(name)
2485        UpdateSubstanceGrid(G2frame,data)
2486       
2487    def AddElement(name):
2488        ElList = data['Substances'][name]['Elements'].keys()
2489        dlg = G2elemGUI.PickElements(G2frame,ElList)
2490        if dlg.ShowModal() == wx.ID_OK:
2491            for El in dlg.Elem:
2492                El = El.strip().upper()
2493                Info = G2elem.GetAtomInfo(El)
2494                Info.update({'Num':1})
2495                data['Substances'][name]['Elements'][El] = Info
2496                data['Substances'][name]['Volume'] = G2mth.El2EstVol(data['Substances'][name]['Elements'])
2497                data['Substances'][name]['Density'] = \
2498                    G2mth.Vol2Den(data['Substances'][name]['Elements'],data['Substances'][name]['Volume'])
2499                data['Substances'][name]['Scatt density'] = \
2500                    G2mth.XScattDen(data['Substances'][name]['Elements'],data['Substances'][name]['Volume'])[0]
2501                contrst,absorb = G2mth.XScattDen(data['Substances'][name]['Elements'],data['Substances'][name]['Volume'],wave)         
2502                data['Substances'][name]['XAnom density'] = contrst
2503                data['Substances'][name]['XAbsorption'] = absorb
2504        dlg.Destroy()
2505       
2506    def OnDeleteElement(event):
2507        TextList = []
2508        for name in data['Substances']:
2509            if name != 'vacuum':
2510                TextList += [name,]
2511        if not TextList:
2512            return
2513        dlg = wx.SingleChoiceDialog(G2frame, 'Which substance?', 'Select substance', TextList, wx.CHOICEDLG_STYLE)
2514        try:
2515            if dlg.ShowModal() == wx.ID_OK:
2516                name = TextList[dlg.GetSelection()]
2517            else:
2518                return
2519        finally:
2520            dlg.Destroy()
2521        ElList = data['Substances'][name]['Elements'].keys()
2522        if len(ElList):
2523            DE = G2elemGUI.DeleteElement(G2frame,ElList)
2524            if DE.ShowModal() == wx.ID_OK:
2525                El = DE.GetDeleteElement().strip().upper()
2526                del(data['Substances'][name]['Elements'][El])
2527                data['Substances'][name]['Volume'] = G2mth.El2EstVol(data['Substances'][name]['Elements'])
2528                data['Substances'][name]['Density'] = \
2529                    G2mth.Vol2Den(data['Substances'][name]['Elements'],data['Substances'][name]['Volume'])
2530                data['Substances'][name]['Scatt density'] = \
2531                    G2mth.XScattDen(data['Substances'][name]['Elements'],data['Substances'][name]['Volume'])[0]
2532                contrst,absorb = G2mth.XScattDen(data['Substances'][name]['Elements'],data['Substances'][name]['Volume'],wave)         
2533                data['Substances'][name]['XAnom density'] = contrst
2534                data['Substances'][name]['XAbsorption'] = absorb
2535        UpdateSubstanceGrid(G2frame,data)
2536               
2537    def SubstSizer():
2538       
2539        def OnValueChange(event):
2540            Obj = event.GetEventObject()
2541            if len(Indx[Obj.GetId()]) == 3:
2542                name,El,keyId = Indx[Obj.GetId()]
2543                try:
2544                    value = max(0,float(Obj.GetValue()))
2545                except ValueError:
2546                    value = 0
2547                    Obj.SetValue('%.2f'%(value))
2548                data['Substances'][name]['Elements'][El][keyId] = value
2549                data['Substances'][name]['Volume'] = G2mth.El2EstVol(data['Substances'][name]['Elements'])
2550                data['Substances'][name]['Density'] = \
2551                    G2mth.Vol2Den(data['Substances'][name]['Elements'],data['Substances'][name]['Volume'])
2552            else:
2553                name,keyId = Indx[Obj.GetId()]
2554                try:
2555                    value = max(0,float(Obj.GetValue()))
2556                except ValueError:
2557                    value = 1.0
2558                data['Substances'][name][keyId] = value
2559                if keyId in 'Volume':
2560                    data['Substances'][name]['Density'] = \
2561                        G2mth.Vol2Den(data['Substances'][name]['Elements'],value)
2562                elif keyId in 'Density':
2563                    data['Substances'][name]['Volume'] = \
2564                        G2mth.Den2Vol(data['Substances'][name]['Elements'],value)
2565            data['Substances'][name]['Scatt density'] = \
2566                G2mth.XScattDen(data['Substances'][name]['Elements'],data['Substances'][name]['Volume'])[0]
2567            contrst,absorb = G2mth.XScattDen(data['Substances'][name]['Elements'],data['Substances'][name]['Volume'],wave)         
2568            data['Substances'][name]['XAnom density'] = contrst
2569            data['Substances'][name]['XAbsorption'] = absorb
2570            wx.CallAfter(UpdateSubstanceGrid,G2frame,data)
2571       
2572        Indx = {}
2573        substSizer = wx.BoxSizer(wx.VERTICAL)
2574        substSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' Substance list: wavelength: %.5fA'%(wave)),
2575            0,WACV)
2576        for name in data['Substances']:
2577            G2gd.HorizontalLine(substSizer,G2frame.dataDisplay)   
2578            substSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' Data for '+name+':'),
2579                0,WACV)
2580            if name == 'vacuum':
2581                substSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label='        Not applicable'),
2582                    0,WACV)
2583            else:   
2584                elSizer = wx.FlexGridSizer(1,6,5,5)
2585                Substance = data['Substances'][name]
2586                Elems = Substance['Elements']
2587                for El in Elems:    #do elements as pull downs for isotopes for neutrons
2588                    elSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' '+El+': '),
2589                        0,WACV)
2590                    num = wx.TextCtrl(G2frame.dataDisplay,value='%.2f'%(Elems[El]['Num']),style=wx.TE_PROCESS_ENTER)
2591                    Indx[num.GetId()] = [name,El,'Num']
2592                    num.Bind(wx.EVT_TEXT_ENTER,OnValueChange)       
2593                    num.Bind(wx.EVT_KILL_FOCUS,OnValueChange)
2594                    elSizer.Add(num,0,WACV)
2595                substSizer.Add(elSizer,0)
2596                vdsSizer = wx.FlexGridSizer(1,4,5,5)
2597                vdsSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' Volume: '),
2598                    0,WACV)
2599                vol = wx.TextCtrl(G2frame.dataDisplay,value='%.3f'%(Substance['Volume']),style=wx.TE_PROCESS_ENTER)
2600                Indx[vol.GetId()] = [name,'Volume']
2601                vol.Bind(wx.EVT_TEXT_ENTER,OnValueChange)       
2602                vol.Bind(wx.EVT_KILL_FOCUS,OnValueChange)
2603                vdsSizer.Add(vol,0,WACV)               
2604                vdsSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' Density: '),
2605                    0,WACV)
2606                den = wx.TextCtrl(G2frame.dataDisplay,value='%.3f'%(Substance['Density']),style=wx.TE_PROCESS_ENTER)
2607                Indx[den.GetId()] = [name,'Density']
2608                den.Bind(wx.EVT_TEXT_ENTER,OnValueChange)       
2609                den.Bind(wx.EVT_KILL_FOCUS,OnValueChange)
2610                vdsSizer.Add(den,0,WACV)
2611                substSizer.Add(vdsSizer,0)
2612                substSizer.Add(wx.StaticText(G2frame.dataDisplay,
2613                    label=' Scattering density  : %.2f *10%scm%s'%(Substance['Scatt density'],Pwr10,Pwrm2)),
2614                    0,WACV)               
2615                substSizer.Add(wx.StaticText(G2frame.dataDisplay,       #allow neutrons here into NAnom density & NAbsorption
2616                    label=' Anomalous density : %.2f *10%scm%s'%(Substance['XAnom density'],Pwr10,Pwrm2)),
2617                    0,WACV)               
2618                substSizer.Add(wx.StaticText(G2frame.dataDisplay,
2619                    label=' X-ray absorption   : %.2f cm%s'%(Substance['XAbsorption'],Pwrm1)),
2620                    0,WACV)               
2621        return substSizer
2622           
2623    Inst = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,G2frame.PatternId, 'Instrument Parameters'))[0]
2624    wave = G2mth.getWave(Inst)
2625    if G2frame.dataDisplay:
2626        G2frame.dataFrame.DestroyChildren()
2627    G2gd.SetDataMenuBar(G2frame,G2frame.dataFrame.SubstanceMenu)
2628    if not G2frame.dataFrame.GetStatusBar():
2629        Status = G2frame.dataFrame.CreateStatusBar()
2630    G2frame.dataDisplay = wxscroll.ScrolledPanel(G2frame.dataFrame)
2631    G2frame.dataFrame.SetLabel('Substances')
2632    G2frame.dataFrame.Bind(wx.EVT_MENU, OnLoadSubstance, id=G2gd.wxID_LOADSUBSTANCE)   
2633    G2frame.dataFrame.Bind(wx.EVT_MENU, OnAddSubstance, id=G2gd.wxID_ADDSUBSTANCE)
2634    G2frame.dataFrame.Bind(wx.EVT_MENU, OnCopySubstance, id=G2gd.wxID_COPYSUBSTANCE)
2635    G2frame.dataFrame.Bind(wx.EVT_MENU, OnDeleteSubstance, id=G2gd.wxID_DELETESUBSTANCE)   
2636    G2frame.dataFrame.Bind(wx.EVT_MENU, OnAddElement, id=G2gd.wxID_ELEMENTADD)
2637    G2frame.dataFrame.Bind(wx.EVT_MENU, OnDeleteElement, id=G2gd.wxID_ELEMENTDELETE)
2638    mainSizer = wx.BoxSizer(wx.VERTICAL)
2639    mainSizer.Add(SubstSizer(),0)
2640
2641    mainSizer.Layout()   
2642    G2frame.dataDisplay.SetSizer(mainSizer)
2643    G2frame.dataDisplay.SetAutoLayout(1)
2644    G2frame.dataDisplay.SetupScrolling()
2645    Size = mainSizer.Fit(G2frame.dataFrame)
2646    Size[0] += 25
2647    G2frame.dataDisplay.SetSize(Size)
2648    G2frame.dataFrame.setSizePosLeft(Size)   
2649       
2650################################################################################
2651#####  SASD Models
2652################################################################################           
2653       
2654def UpdateModelsGrid(G2frame,data):
2655    '''respond to selection of SASD Models data tree item.
2656    '''
2657    #patches
2658    if 'Current' not in data:
2659        data['Current'] = 'Size dist.'
2660    if 'logBins' not in data['Size']:
2661        data['Size']['logBins'] = True
2662    if 'MinMaxDiam' in data['Size']:
2663        data['Size']['MinDiam'] = 50.
2664        data['Size']['MaxDiam'] = 10000.
2665        del data['Size']['MinMaxDiam']
2666    if isinstance(data['Size']['MaxEnt']['Sky'],float):
2667        data['Size']['MaxEnt']['Sky'] = -3
2668    if 'Power' not in data['Size']['IPG']:
2669        data['Size']['IPG']['Power'] = -1
2670    if 'Matrix' not in data['Particle']:
2671        data['Particle']['Matrix'] = {'Name':'vacuum','VolFrac':[0.0,False]}
2672    if 'BackFile' not in data:
2673        data['BackFile'] = ''
2674    #end patches
2675   
2676    def RefreshPlots(newPlot=False):
2677        PlotText = G2frame.G2plotNB.nb.GetPageText(G2frame.G2plotNB.nb.GetSelection())
2678        if 'Powder' in PlotText:
2679            G2plt.PlotPatterns(G2frame,plotType='SASD',newPlot=newPlot)
2680        elif 'Size' in PlotText:
2681            G2plt.PlotSASDSizeDist(G2frame)
2682               
2683    def OnAddModel(event):
2684        if data['Current'] == 'Particle fit':
2685            material = 'vacuum'
2686            if len(data['Particle']['Levels']):
2687                material = data['Particle']['Levels'][-1]['Controls']['Material']
2688            data['Particle']['Levels'].append({
2689                'Controls':{'FormFact':'Sphere','DistType':'LogNormal','Material':material,
2690                    'FFargs':{},'SFargs':{},'NumPoints':50,'Cutoff':0.01,'Contrast':0.0,
2691                    'SlitSmear':[0.0,False],'StrFact':'Dilute'},    #last 2 not used - future?
2692                'LogNormal':{'Volume':[0.05,False],'Mean':[1000.,False],'StdDev':[0.5,False],'MinSize':[10.,False],},
2693                'Gaussian':{'Volume':[0.05,False],'Mean':[1000.,False],'StdDev':[300.,False],},
2694                'LSW':{'Volume':[0.05,False],'Mean':[1000.0,False],},
2695                'Schulz-Zimm':{'Volume':[0.05,False],'Mean':[1000.,False],'StdDev':[300.,False],},
2696                'Unified':{'G':[1.e3,False],'Rg':[100,False],'B':[1.e-5,False],'P':[4,False],'Cutoff':[1e-5,False],},
2697                'Porod':{'B':[1.e-4,False],'P':[4,False],'Cutoff':[1e-5,False],},
2698                'Monodisperse':{'Volume':[0.05,False],'Radius':[100,False],},   #OK for spheres
2699                'Bragg':{'PkInt':[100,False],'PkPos':[0.2,False],
2700                    'PkSig':[10,False],'PkGam':[10,False],},        #reasonable 31A peak
2701                })
2702            G2sasd.ModelFxn(Profile,ProfDict,Limits,Sample,data)
2703            RefreshPlots(True)
2704                   
2705        wx.CallAfter(UpdateModelsGrid,G2frame,data)
2706       
2707    def OnCopyModel(event):
2708        hst = G2frame.PatternTree.GetItemText(G2frame.PatternId)
2709        histList = GetHistsLikeSelected(G2frame)
2710        if not histList:
2711            G2frame.ErrorDialog('No match','No histograms match '+hst,G2frame.dataFrame)
2712            return
2713        copyList = []
2714        dlg = G2gd.G2MultiChoiceDialog(
2715            G2frame.dataFrame, 
2716            'Copy models from\n'+hst[5:]+' to...',
2717            'Copy models', histList)
2718        try:
2719            if dlg.ShowModal() == wx.ID_OK:
2720                for i in dlg.GetSelections(): 
2721                    copyList.append(histList[i])
2722        finally:
2723            dlg.Destroy()       
2724        for item in copyList:
2725            Id = G2gd.GetPatternTreeItemId(G2frame,G2frame.root,item)
2726            newdata = copy.deepcopy(data)
2727            G2frame.PatternTree.SetItemPyData(G2gd.GetPatternTreeItemId(G2frame,Id,'Models'),newdata)
2728            if newdata['BackFile']:
2729                Profile = G2frame.PatternTree.GetItemPyData(Id)[1]
2730                BackId = G2gd.GetPatternTreeItemId(G2frame,G2frame.root,newdata['BackFile'])
2731                BackSample = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,BackId, 'Sample Parameters'))
2732                Profile[5] = BackSample['Scale'][0]*G2frame.PatternTree.GetItemPyData(BackId)[1][1]
2733        RefreshPlots(True)
2734               
2735    def OnCopyFlags(event):
2736        thisModel = copy.deepcopy(data)
2737        hst = G2frame.PatternTree.GetItemText(G2frame.PatternId)
2738        histList = GetHistsLikeSelected(G2frame)
2739        if not histList:
2740            G2frame.ErrorDialog('No match','No histograms match '+hst,G2frame.dataFrame)
2741            return
2742        dlg = G2gd.G2MultiChoiceDialog(
2743            G2frame.dataFrame, 
2744            'Copy sample ref. flags from\n'+str(hst[5:])+' to...',
2745            'Copy sample flags', histList)
2746        distChoice = ['LogNormal','Gaussian','LSW','Schulz-Zimm','Bragg','Unified',
2747            'Porod','Monodisperse',]
2748        parmOrder = ['Volume','Radius','Mean','StdDev','G','Rg','B','P',
2749            'Cutoff','PkInt','PkPos','PkSig','PkGam','VolFr','Dist',]
2750        try:
2751            if dlg.ShowModal() == wx.ID_OK:
2752                result = dlg.GetSelections()
2753                for i in result: 
2754                    item = histList[i]
2755                    Id = G2gd.GetPatternTreeItemId(G2frame,G2frame.root,item)
2756                    newModel = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,Id,'Models'))
2757                    newModel['Back'][1] = copy.copy(thisModel['Back'][1])
2758                    for ilev,level in enumerate(newModel['Particle']['Levels']):
2759                        for form in level:
2760                            if form in distChoice:
2761                                thisForm = thisModel['Particle']['Levels'][ilev][form]                               
2762                                for item in parmOrder:
2763                                    if item in thisForm:
2764                                       level[form][item][1] = copy.copy(thisForm[item][1])
2765                            elif form == 'Controls':
2766                                thisForm = thisModel['Particle']['Levels'][ilev][form]['SFargs']
2767                                for item in parmOrder:
2768                                    if item in thisForm:
2769                                        level[form]['SFargs'][item][1] = copy.copy(thisForm[item][1])
2770        finally:
2771            dlg.Destroy()
2772               
2773    def OnFitModelAll(event):
2774        choices = G2gd.GetPatternTreeDataNames(G2frame,['SASD',])
2775        sel = []
2776        dlg = G2gd.G2MultiChoiceDialog(G2frame.dataFrame, 'Sequential SASD refinement',
2777             'Select dataset to include',choices)
2778        dlg.SetSelections(sel)
2779        names = []
2780        if dlg.ShowModal() == wx.ID_OK:
2781            for sel in dlg.GetSelections():
2782                names.append(choices[sel])
2783        dlg.Destroy()
2784        SeqResult = {'histNames':names}
2785        Reverse = False
2786        CopyForward = False
2787        choice = ['Reverse sequence','Copy from prev.']
2788        dlg = wx.MultiChoiceDialog(G2frame.dataFrame,'Sequential controls','Select controls',choice)
2789        if dlg.ShowModal() == wx.ID_OK:
2790            for sel in dlg.GetSelections():
2791                if sel:
2792                    CopyForward = True
2793                else:
2794                    G2frame.seqReverse = True
2795        dlg.Destroy()
2796        dlg = wx.ProgressDialog('SASD Sequential fit','Data set name = '+names[0],len(names), 
2797            style = wx.PD_ELAPSED_TIME|wx.PD_AUTO_HIDE|wx.PD_REMAINING_TIME|wx.PD_CAN_ABORT)
2798        wx.BeginBusyCursor()
2799        if G2frame.seqReverse:
2800            names.reverse()
2801        try:
2802            for i,name in enumerate(names):
2803                print ' Sequential fit for ',name
2804                GoOn = dlg.Update(i,newmsg='Data set name = '+name)[0]
2805                if not GoOn:
2806                    break
2807                Id =  G2gd.GetPatternTreeItemId(G2frame,G2frame.root,name)
2808                if i and CopyForward:
2809                    G2frame.PatternTree.SetItemPyData(G2gd.GetPatternTreeItemId(G2frame,Id, 'Models'),JModel)
2810                IProfDict,IProfile = G2frame.PatternTree.GetItemPyData(Id)[:2]
2811                IModel = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,Id, 'Models'))
2812                ISample = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,Id, 'Sample Parameters'))
2813                ILimits = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,Id, 'Limits'))
2814                IInst = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,Id, 'Instrument Parameters'))
2815                IfOK,result,varyList,sig,Rvals,covMatrix,parmDict,Msg = G2sasd.ModelFit(IProfile,IProfDict,ILimits,ISample,IModel)
2816                JModel = copy.copy(IModel)
2817                if not IfOK:
2818                    G2frame.ErrorDialog('Failed sequential refinement for data '+name,
2819                        ' Msg: '+Msg+'\nYou need to rethink your selection of parameters\n'+    \
2820                        ' Model restored to previous version for'+name)
2821                    SeqResult['histNames'] = names[:i]
2822                    dlg.Destroy()
2823                    break
2824               
2825                G2sasd.ModelFxn(IProfile,IProfDict,ILimits,ISample,IModel)
2826                SeqResult[name] = {'variables':result[0],'varyList':varyList,'sig':sig,'Rvals':Rvals,
2827                    'covMatrix':covMatrix,'title':name,'parmDict':parmDict}
2828            else:
2829                dlg.Destroy()
2830                print ' ***** Small angle sequential refinement successful *****'
2831        finally:
2832            wx.EndBusyCursor()   
2833        Id =  G2gd.GetPatternTreeItemId(G2frame,G2frame.root,'Sequential results')
2834        if Id:
2835            G2frame.PatternTree.SetItemPyData(Id,SeqResult)
2836        else:
2837            Id = G2frame.PatternTree.AppendItem(parent=G2frame.root,text='Sequential results')
2838            G2frame.PatternTree.SetItemPyData(Id,SeqResult)
2839        G2frame.PatternTree.SelectItem(Id)
2840       
2841    def OnFitModel(event):
2842        if data['Current'] == 'Size dist.':
2843            if not any(Sample['Contrast']):
2844                G2frame.ErrorDialog('No contrast; your sample is a vacuum!',
2845                    'You need to define a scattering substance!\n'+    \
2846                    ' Do Substances and then Sample parameters')
2847                return
2848            G2sasd.SizeDistribution(Profile,ProfDict,Limits,Sample,data)
2849            G2plt.PlotSASDSizeDist(G2frame)
2850            RefreshPlots(True)
2851           
2852        elif data['Current'] == 'Particle fit':
2853            SaveState()
2854            Results = G2sasd.ModelFit(Profile,ProfDict,Limits,Sample,data)
2855            if not Results[0]:
2856                    G2frame.ErrorDialog('Failed refinement',
2857                        ' Msg: '+Results[-1]+'\nYou need to rethink your selection of parameters\n'+    \
2858                        ' Model restored to previous version')
2859            G2sasd.ModelFxn(Profile,ProfDict,Limits,Sample,data)
2860            RefreshPlots(True)
2861            wx.CallAfter(UpdateModelsGrid,G2frame,data)
2862           
2863    def OnUnDo(event):
2864        DoUnDo()
2865        data = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,
2866            G2frame.PatternId,'Models'))
2867        G2frame.dataFrame.SasdUndo.Enable(False)
2868        UpdateModelsGrid(G2frame,data)
2869        G2sasd.ModelFxn(Profile,ProfDict,Limits,Sample,data)
2870        RefreshPlots(True)
2871
2872    def DoUnDo():
2873        print 'Undo last refinement'
2874        file = open(G2frame.undosasd,'rb')
2875        PatternId = G2frame.PatternId
2876        G2frame.PatternTree.SetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId, 'Models'),cPickle.load(file))
2877        print ' Models recovered'
2878        file.close()
2879       
2880    def SaveState():
2881        G2frame.undosasd = os.path.join(G2frame.dirname,'GSASIIsasd.save')
2882        file = open(G2frame.undosasd,'wb')
2883        PatternId = G2frame.PatternId
2884        for item in ['Models']:
2885            cPickle.dump(G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId,item)),file,1)
2886        file.close()
2887        G2frame.dataFrame.SasdUndo.Enable(True)
2888       
2889    def OnSelectFit(event):
2890        data['Current'] = fitSel.GetValue()
2891        wx.CallAfter(UpdateModelsGrid,G2frame,data)
2892       
2893    def OnCheckBox(event):
2894        Obj = event.GetEventObject()
2895        item,ind = Indx[Obj.GetId()]
2896        item[ind] = Obj.GetValue()
2897       
2898    def OnIntVal(event):
2899        Obj = event.GetEventObject()
2900        item,ind,minVal = Indx[Obj.GetId()]
2901        try:
2902            value = int(Obj.GetValue())
2903            if value <= minVal:
2904                raise ValueError
2905        except ValueError:
2906            value = item[ind]
2907        Obj.SetValue(str(value))
2908        item[ind] = value
2909
2910    def SizeSizer():
2911       
2912        def OnShape(event):
2913            data['Size']['Shape'][0] = partsh.GetValue()
2914            wx.CallAfter(UpdateModelsGrid,G2frame,data)
2915           
2916        def OnMethod(event):
2917            data['Size']['Method'] = method.GetValue()
2918            wx.CallAfter(UpdateModelsGrid,G2frame,data)
2919           
2920        def OnPartVal(event):
2921            try:
2922                val = max(0.0,float(partprm.GetValue()))
2923            except ValueError:
2924                val = 1
2925            data['Size']['Shape'][1] = val
2926            partprm.SetValue('%.3f'%(val))
2927           
2928        sizeSizer = wx.BoxSizer(wx.VERTICAL)
2929        sizeSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Size distribution parameters: '),0,WACV)
2930        binSizer = wx.FlexGridSizer(1,7,5,5)
2931        binSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' No. size bins: '),0,WACV)
2932        bins = ['50','100','150','200']
2933        nbins = wx.ComboBox(G2frame.dataDisplay,value=str(data['Size']['Nbins']),choices=bins,
2934            style=wx.CB_READONLY|wx.CB_DROPDOWN)
2935        Indx[nbins.GetId()] = [data['Size'],'Nbins',0]
2936        nbins.Bind(wx.EVT_COMBOBOX,OnIntVal)       
2937        binSizer.Add(nbins,0,WACV)
2938        binSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Min diam.: '),0,WACV)
2939        minDias = ['10','25','50','100','150','200']
2940        mindiam = wx.ComboBox(G2frame.dataDisplay,value=str(data['Size']['MinDiam']),choices=minDias,
2941            style=wx.CB_DROPDOWN)
2942        mindiam.Bind(wx.EVT_LEAVE_WINDOW,OnIntVal)
2943        mindiam.Bind(wx.EVT_TEXT_ENTER,OnIntVal)       
2944        mindiam.Bind(wx.EVT_KILL_FOCUS,OnIntVal)
2945        Indx[mindiam.GetId()] = [data['Size'],'MinDiam',0]
2946        binSizer.Add(mindiam,0,WACV)
2947        binSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Max diam.: '),0,WACV)
2948        maxDias = [str(1000*(i+1)) for i in range(10)]
2949        maxdiam = wx.ComboBox(G2frame.dataDisplay,value=str(data['Size']['MaxDiam']),choices=maxDias,
2950            style=wx.CB_DROPDOWN)
2951        maxdiam.Bind(wx.EVT_LEAVE_WINDOW,OnIntVal)
2952        maxdiam.Bind(wx.EVT_TEXT_ENTER,OnIntVal)       
2953        maxdiam.Bind(wx.EVT_KILL_FOCUS,OnIntVal)
2954        Indx[maxdiam.GetId()] = [data['Size'],'MaxDiam',0]
2955        binSizer.Add(maxdiam,0,WACV)
2956        logbins = wx.CheckBox(G2frame.dataDisplay,label='Log bins?')
2957        Indx[logbins.GetId()] = [data['Size'],'logBins']
2958        logbins.SetValue(data['Size']['logBins'])
2959        logbins.Bind(wx.EVT_CHECKBOX, OnCheckBox)
2960        binSizer.Add(logbins,0,WACV)
2961        sizeSizer.Add(binSizer,0)
2962        sizeSizer.Add((5,5),0)
2963        partSizer = wx.BoxSizer(wx.HORIZONTAL)
2964        partSizer.Add(wx.StaticText(G2frame.dataDisplay,label='Particle description: '),0,WACV)
2965        shapes = {'Spheroid':' Aspect ratio: ','Cylinder':' Diameter ','Cylinder AR':' Aspect ratio: ',
2966            'Unified sphere':'','Unified rod':' Diameter: ','Unified rod AR':' Aspect ratio: ',
2967            'Unified disk':' Thickness: '}
2968        partsh = wx.ComboBox(G2frame.dataDisplay,value=str(data['Size']['Shape'][0]),choices=shapes.keys(),
2969            style=wx.CB_READONLY|wx.CB_DROPDOWN)
2970        partsh.Bind(wx.EVT_COMBOBOX,OnShape)       
2971        partSizer.Add(partsh,0,WACV)
2972        if data['Size']['Shape'][0] not in ['Unified sphere',]:
2973            partSizer.Add(wx.StaticText(G2frame.dataDisplay,label=shapes[data['Size']['Shape'][0]]),0,WACV)
2974            partprm = wx.TextCtrl(G2frame.dataDisplay,value='%.3f'%(data['Size']['Shape'][1]),
2975                style=wx.TE_PROCESS_ENTER)
2976            partprm.Bind(wx.EVT_TEXT_ENTER,OnPartVal)       
2977            partprm.Bind(wx.EVT_KILL_FOCUS,OnPartVal)
2978            partSizer.Add(partprm,0,WACV)
2979        sizeSizer.Add(partSizer,0)
2980        sizeSizer.Add((5,5),0)
2981        fitSizer = wx.BoxSizer(wx.HORIZONTAL)
2982        methods = ['MaxEnt','IPG',]
2983        fitSizer.Add(wx.StaticText(G2frame.dataDisplay,label='Fitting method: '),0,WACV)
2984        method = wx.ComboBox(G2frame.dataDisplay,value=data['Size']['Method'],choices=methods,
2985            style=wx.CB_READONLY|wx.CB_DROPDOWN)
2986        method.Bind(wx.EVT_COMBOBOX,OnMethod)
2987        fitSizer.Add(method,0,WACV)
2988        iters = ['10','25','50','100','150','200']       
2989        fitSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' No. iterations: '),0,WACV)
2990        Method = data['Size']['Method']
2991        iter = wx.ComboBox(G2frame.dataDisplay,value=str(data['Size'][Method]['Niter']),choices=iters,
2992            style=wx.CB_READONLY|wx.CB_DROPDOWN)
2993        Indx[iter.GetId()] = [data['Size'][Method],'Niter',0]
2994        iter.Bind(wx.EVT_COMBOBOX,OnIntVal)
2995        fitSizer.Add(iter,0,WACV)
2996        if 'MaxEnt' in data['Size']['Method']:
2997            fitSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Log floor factor: '),0,WACV)
2998            floors = [str(-i) for i in range(9)]
2999            floor = wx.ComboBox(G2frame.dataDisplay,value=str(data['Size']['MaxEnt']['Sky']),choices=floors,
3000                style=wx.CB_READONLY|wx.CB_DROPDOWN)
3001            Indx[floor.GetId()] = [data['Size']['MaxEnt'],'Sky',-10]
3002            floor.Bind(wx.EVT_COMBOBOX,OnIntVal)
3003            fitSizer.Add(floor,0,WACV)
3004        elif 'IPG' in data['Size']['Method']:
3005            fitSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Q power weight (-1 for sigma): '),0,WACV)
3006            choices = ['-1','0','1','2','3','4']
3007            power = wx.ComboBox(G2frame.dataDisplay,value=str(data['Size']['IPG']['Power']),choices=choices,
3008                style=wx.CB_READONLY|wx.CB_DROPDOWN)
3009            Indx[power.GetId()] = [data['Size']['IPG'],'Power',-2]
3010            power.Bind(wx.EVT_COMBOBOX,OnIntVal)
3011            fitSizer.Add(power,0,WACV)
3012        sizeSizer.Add(fitSizer,0)
3013
3014        return sizeSizer
3015       
3016    def PartSizer():
3017       
3018        FormFactors = {'Sphere':{},'Spheroid':{'Aspect ratio':[1.0,False]},
3019            'Cylinder':{'Length':[100.,False]},'Cylinder diam':{'Diameter':[100.,False]},
3020            'Cylinder AR':{'Aspect ratio':[1.0,False]},'Unified sphere':{},
3021            'Unified rod':{'Length':[100.,False]},'Unified rod AR':{'Aspect ratio':[1.0,False]},
3022            'Unified disk':{'Thickness':[100.,False]},
3023            'Unified tube':{'Length':[100.,False],'Thickness':[10.,False]},}
3024               
3025        StructureFactors = {'Dilute':{},'Hard sphere':{'VolFr':[0.1,False],'Dist':[100.,False]},
3026            'Sticky hard sphere':{'VolFr':[0.1,False],'Dist':[100.,False],'epis':[0.05,False],'Sticky':[0.2,False]},
3027            'Square well':{'VolFr':[0.1,False],'Dist':[100.,False],'Depth':[0.1,False],'Width':[1.,False]},
3028            'InterPrecipitate':{'VolFr':[0.1,False],'Dist':[100.,False]},}
3029               
3030        ffDistChoices =  ['Sphere','Spheroid','Cylinder','Cylinder diam',
3031            'Cylinder AR','Unified sphere','Unified rod','Unified rod AR',
3032            'Unified disk','Unified tube',]
3033               
3034        ffMonoChoices = ['Sphere','Spheroid','Cylinder','Cylinder AR',]
3035       
3036        sfChoices = ['Dilute','Hard sphere','Sticky hard sphere','Square well','InterPrecipitate',]
3037           
3038        slMult = 1000.
3039                 
3040        def OnValue(event):
3041            Obj = event.GetEventObject()
3042            item,key,sldrObj = Indx[Obj.GetId()]
3043            try:
3044                value = float(Obj.GetValue())
3045                if value <= 0.:
3046                    raise ValueError
3047            except ValueError:
3048                value = item[key][0]
3049            item[key][0] = value
3050            Obj.SetValue('%.3g'%(value))
3051            if key in ['P','epis','Sticky','Depth','Width','VolFr','Dist']:
3052                sldrObj.SetValue(slMult*value)
3053            else:
3054                logv = np.log10(value)
3055                valMinMax = [logv-1,logv+1]
3056                sldrObj.SetRange(slMult*valMinMax[0],slMult*valMinMax[1])
3057                sldrObj.SetValue(slMult*logv)
3058            G2sasd.ModelFxn(Profile,ProfDict,Limits,Sample,data)
3059            RefreshPlots()
3060           
3061        def OnSelect(event):
3062            Obj = event.GetEventObject()
3063            item,key = Indx[Obj.GetId()]
3064            item[key] = Obj.GetValue()
3065            if 'Refine' not in Obj.GetLabel():
3066                if 'FormFact' in key :
3067                    item['FFargs'] = FormFactors[Obj.GetValue()]
3068                elif 'StrFact' in key:
3069                    item['SFargs'] = StructureFactors[Obj.GetValue()]
3070                wx.CallAfter(UpdateModelsGrid,G2frame,data)
3071                G2sasd.ModelFxn(Profile,ProfDict,Limits,Sample,data)
3072                RefreshPlots()
3073               
3074        def OnDelLevel(event):
3075            Obj = event.GetEventObject()
3076            item = Indx[Obj.GetId()]
3077            del data['Particle']['Levels'][item]
3078            wx.CallAfter(UpdateModelsGrid,G2frame,data)
3079            G2sasd.ModelFxn(Profile,ProfDict,Limits,Sample,data)
3080            RefreshPlots()
3081           
3082        def OnParmSlider(event):
3083            Obj = event.GetEventObject()
3084            item,key,pvObj = Indx[Obj.GetId()]
3085            slide = Obj.GetValue()
3086            if key in ['P','epis','Sticky','Depth','Width','VolFr','Dist']:
3087                value = float(slide/slMult)
3088            else:
3089                value = 10.**float(slide/slMult)
3090            item[key][0] = value
3091            pvObj.SetValue('%.3g'%(item[key][0]))
3092            G2sasd.ModelFxn(Profile,ProfDict,Limits,Sample,data)
3093            RefreshPlots()
3094           
3095        def SizeSizer():
3096            sizeSizer = wx.FlexGridSizer(0,4,5,5)
3097            sizeSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Distribution: '),0,WACV)
3098            Distchoice = ['LogNormal','Gaussian','LSW','Schulz-Zimm','Bragg','Unified','Porod','Monodisperse',]
3099            distChoice = wx.ComboBox(G2frame.dataDisplay,value=level['Controls']['DistType'],choices=Distchoice,
3100                style=wx.CB_READONLY|wx.CB_DROPDOWN)
3101            Indx[distChoice.GetId()] = [level['Controls'],'DistType']
3102            distChoice.Bind(wx.EVT_COMBOBOX,OnSelect)
3103            sizeSizer.Add(distChoice,0,WACV)    #put structure factor choices here
3104            if level['Controls']['DistType'] not in ['Bragg','Unified','Porod',]:
3105                sizeSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Form Factor: '),0,WACV)
3106                if 'Mono' in level['Controls']['DistType']:
3107                    ffChoice = wx.ComboBox(G2frame.dataDisplay,value=level['Controls']['FormFact'],choices=ffMonoChoices,
3108                        style=wx.CB_READONLY|wx.CB_DROPDOWN)
3109                else:
3110                    ffChoice = wx.ComboBox(G2frame.dataDisplay,value=level['Controls']['FormFact'],choices=ffDistChoices,
3111                        style=wx.CB_READONLY|wx.CB_DROPDOWN)
3112                Indx[ffChoice.GetId()] = [level['Controls'],'FormFact']
3113                ffChoice.Bind(wx.EVT_COMBOBOX,OnSelect)
3114                sizeSizer.Add(ffChoice,0,WACV)
3115               
3116                sizeSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Material: '),0,WACV)
3117                matSel = wx.ComboBox(G2frame.dataDisplay,value=level['Controls']['Material'],
3118                    choices=Substances['Substances'].keys(),style=wx.CB_READONLY|wx.CB_DROPDOWN)
3119                Indx[matSel.GetId()] = [level['Controls'],'Material']
3120                matSel.Bind(wx.EVT_COMBOBOX,OnSelect)       
3121                sizeSizer.Add(matSel,0,WACV) #do neutron test here?
3122                rho = Substances['Substances'][level['Controls']['Material']].get('XAnom density',0.0)
3123                level['Controls']['Contrast'] = contrast = (rho-rhoMat)**2                 
3124                sizeSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Resonant X-ray contrast: '),0,WACV)
3125                sizeSizer.Add(wx.StaticText(G2frame.dataDisplay,label=%.2f 10%scm%s'%(contrast,Pwr20,Pwrm4)),0,WACV)
3126                if 'Mono' not in level['Controls']['DistType']:
3127                    sizeSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Num. radii: '),0,WACV)
3128                    radii = ['25','50','75','100','200']
3129                    nRadii = wx.ComboBox(G2frame.dataDisplay,value=str(level['Controls']['NumPoints']),choices=radii,
3130                        style=wx.CB_READONLY|wx.CB_DROPDOWN)
3131                    Indx[nRadii.GetId()] = [level['Controls'],'NumPoints']
3132                    nRadii.Bind(wx.EVT_COMBOBOX,OnSelect)
3133                    sizeSizer.Add(nRadii,0,WACV)
3134                    sizeSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' R dist. cutoff: '),0,WACV)
3135                    rCutoff = G2gd.ValidatedTxtCtrl(G2frame.dataDisplay,level['Controls'],'Cutoff',
3136                        min=0.001,max=0.1,typeHint=float)
3137                    sizeSizer.Add(rCutoff,0,WACV)
3138            elif level['Controls']['DistType']  in ['Unified',]:
3139                Parms = level['Unified']
3140                Best = G2sasd.Bestimate(Parms['G'][0],Parms['Rg'][0],Parms['P'][0])
3141                sizeSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Estimated Dist B: %12.4g'%(Best)),0,WACV)
3142            return sizeSizer
3143           
3144        def ParmSizer():
3145            parmSizer = wx.FlexGridSizer(1,3,5,5)
3146            parmSizer.AddGrowableCol(2,1)
3147            parmSizer.SetFlexibleDirection(wx.HORIZONTAL)
3148            Parms = level[level['Controls']['DistType']]
3149            FFargs = level['Controls']['FFargs']
3150            SFargs = level['Controls'].get('SFargs',{})
3151            parmOrder = ['Volume','Radius','Mean','StdDev','MinSize','G','Rg','B','P','Cutoff',
3152                'PkInt','PkPos','PkSig','PkGam',]
3153            for parm in parmOrder:
3154                if parm in Parms:
3155                    if parm == 'MinSize':
3156                        parmSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Dist '+parm),0,wx.ALIGN_CENTER)
3157                    else:
3158                        parmVar = wx.CheckBox(G2frame.dataDisplay,label='Refine? Dist '+parm) 
3159                        parmVar.SetValue(Parms[parm][1])
3160                        parmVar.Bind(wx.EVT_CHECKBOX, OnSelect)
3161                        parmSizer.Add(parmVar,0,WACV)
3162                        Indx[parmVar.GetId()] = [Parms[parm],1]
3163                    parmValue = wx.TextCtrl(G2frame.dataDisplay,value='%.3g'%(Parms[parm][0]),
3164                        style=wx.TE_PROCESS_ENTER)
3165                    parmValue.Bind(wx.EVT_TEXT_ENTER,OnValue)       
3166                    parmValue.Bind(wx.EVT_KILL_FOCUS,OnValue)
3167                    parmSizer.Add(parmValue,0,WACV)
3168                    if parm == 'P':
3169                        value = Parms[parm][0]
3170                        valMinMax = [0.1,4.2]
3171                    else:
3172                        value = np.log10(Parms[parm][0])
3173                        valMinMax = [value-1,value+1]
3174                    parmSldr = wx.Slider(G2frame.dataDisplay,minValue=slMult*valMinMax[0],
3175                        maxValue=slMult*valMinMax[1],value=slMult*value)
3176                    Indx[parmValue.GetId()] = [Parms,parm,parmSldr]
3177                    Indx[parmSldr.GetId()] = [Parms,parm,parmValue]
3178                    parmSldr.Bind(wx.EVT_SLIDER,OnParmSlider)
3179                    parmSizer.Add(parmSldr,1,wx.EXPAND)
3180            if level['Controls']['DistType'] not in ['Bragg']:
3181                parmOrder = ['Aspect ratio','Length','Diameter','Thickness','VolFr','Dist','epis','Sticky','Depth','Width']
3182                fTypes = ['FF ','SF ']
3183                for iarg,Args in enumerate([FFargs,SFargs]):
3184                    for parm in parmOrder:
3185                        if parm in Args:
3186                            parmVar = wx.CheckBox(G2frame.dataDisplay,label='Refine? '+fTypes[iarg]+parm) 
3187                            parmVar.SetValue(Args[parm][1])
3188                            Indx[parmVar.GetId()] = [Args[parm],1]
3189                            parmVar.Bind(wx.EVT_CHECKBOX, OnSelect)
3190                            parmSizer.Add(parmVar,0,WACV)
3191                            parmValue = wx.TextCtrl(G2frame.dataDisplay,value='%.3g'%(Args[parm][0]),
3192                                style=wx.TE_PROCESS_ENTER)
3193                            parmValue.Bind(wx.EVT_TEXT_ENTER,OnValue)       
3194                            parmValue.Bind(wx.EVT_KILL_FOCUS,OnValue)
3195                            parmSizer.Add(parmValue,0,WACV)
3196                            value = Args[parm][0]
3197                            if parm == 'epis':
3198                                valMinMax = [0,.1]
3199                            elif parm in ['Sticky','Width',]:
3200                                valMinMax = [0,1.]
3201                            elif parm == 'Depth':
3202                                valMinMax = [-2.,2.]
3203                            elif parm == 'Dist':
3204                                valMinMax = [100.,1000.]
3205                            elif parm == 'VolFr':
3206                                valMinMax = [1.e-4,1.]
3207                            else:
3208                                value = np.log10(Args[parm][0])
3209                                valMinMax = [value-1,value+1]
3210                            parmSldr = wx.Slider(G2frame.dataDisplay,minValue=slMult*valMinMax[0],
3211                                maxValue=slMult*valMinMax[1],value=slMult*value)
3212                            Indx[parmVar.GetId()] = [Args[parm],1]
3213                            Indx[parmValue.GetId()] = [Args,parm,parmSldr]
3214                            Indx[parmSldr.GetId()] = [Args,parm,parmValue]
3215                            parmSldr.Bind(wx.EVT_SLIDER,OnParmSlider)
3216                            parmSizer.Add(parmSldr,1,wx.EXPAND)
3217            return parmSizer               
3218           
3219        Indx = {}
3220        partSizer = wx.BoxSizer(wx.VERTICAL)
3221        topSizer = wx.BoxSizer(wx.HORIZONTAL)
3222        topSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Particle fit parameters: '),0,WACV)
3223        topSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Matrix: '),0,WACV)
3224        matsel = wx.ComboBox(G2frame.dataDisplay,value=data['Particle']['Matrix']['Name'],
3225            choices=Substances['Substances'].keys(),style=wx.CB_READONLY|wx.CB_DROPDOWN)
3226        Indx[matsel.GetId()] = [data['Particle']['Matrix'],'Name'] 
3227        matsel.Bind(wx.EVT_COMBOBOX,OnSelect) #Do neutron test here?
3228        rhoMat = Substances['Substances'][data['Particle']['Matrix']['Name']].get('XAnom density',0.0)       
3229        topSizer.Add(matsel,0,WACV)
3230        topSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Volume fraction: '),0,WACV)
3231        volfrac = G2gd.ValidatedTxtCtrl(G2frame.dataDisplay,data['Particle']['Matrix']['VolFrac'],0,
3232                typeHint=float)
3233        topSizer.Add(volfrac,0,WACV)
3234        volVar = wx.CheckBox(G2frame.dataDisplay,label=' Refine?')
3235        volVar.SetValue(data['Particle']['Matrix']['VolFrac'][1])
3236        Indx[volVar.GetId()] = [data['Particle']['Matrix']['VolFrac'],1]
3237        volVar.Bind(wx.EVT_CHECKBOX, OnSelect)
3238        topSizer.Add(volVar,0,WACV)
3239        partSizer.Add(topSizer,0,)
3240        for ilev,level in enumerate(data['Particle']['Levels']):
3241            G2gd.HorizontalLine(partSizer,G2frame.dataDisplay)
3242            topLevel = wx.BoxSizer(wx.HORIZONTAL)
3243            topLevel.Add(wx.StaticText(G2frame.dataDisplay,label=' Model component %d: '%(ilev)),0,WACV)
3244            delBtn = wx.Button(G2frame.dataDisplay,label=' Delete?')
3245            Indx[delBtn.GetId()] = ilev
3246            delBtn.Bind(wx.EVT_BUTTON,OnDelLevel)
3247            topLevel.Add(delBtn,0,WACV)
3248            partSizer.Add(topLevel,0)
3249            partSizer.Add(SizeSizer())
3250            if level['Controls']['DistType'] not in ['Bragg','Unified','Porod',]:
3251                topLevel.Add(wx.StaticText(G2frame.dataDisplay,label=' Structure factor: '),0,WACV)
3252                strfctr = wx.ComboBox(G2frame.dataDisplay,value=level['Controls']['StrFact'],
3253                    choices=sfChoices,style=wx.CB_READONLY|wx.CB_DROPDOWN)
3254                Indx[strfctr.GetId()] = [level['Controls'],'StrFact']
3255                strfctr.Bind(wx.EVT_COMBOBOX,OnSelect)
3256                topLevel.Add(strfctr,0,WACV)
3257            partSizer.Add(ParmSizer(),0,wx.EXPAND)
3258        return partSizer
3259       
3260    def OnEsdScale(event):
3261        try:
3262            value = float(esdScale.GetValue())
3263            if value <= 0.:
3264                raise ValueError
3265        except ValueError:
3266            value = 1./np.sqrt(ProfDict['wtFactor'])
3267        ProfDict['wtFactor'] = 1./value**2
3268        esdScale.SetValue('%.3f'%(value))
3269        RefreshPlots(True)
3270       
3271    def OnBackChange(event):
3272        try:
3273            value = float(backVal.GetValue())
3274        except ValueError:
3275            value = 0.0
3276        backVal.SetValue('%.3g'%(value))
3277        data['Back'][0] = value
3278        Profile[4][:] = value
3279        RefreshPlots()
3280       
3281    def OnBackFile(event):
3282        data['BackFile'] = backFile.GetValue()
3283        if data['BackFile']:
3284            fixBack =  data['Back'][0]
3285            BackId = G2gd.GetPatternTreeItemId(G2frame,G2frame.root,data['BackFile'])
3286            BackSample = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,BackId, 'Sample Parameters'))
3287            Profile[5] = BackSample['Scale'][0]*G2frame.PatternTree.GetItemPyData(BackId)[1][1]
3288            RefreshPlots(True)
3289           
3290    Sample = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,G2frame.PatternId, 'Sample Parameters'))
3291    Limits = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,G2frame.PatternId, 'Limits'))
3292    Inst = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,G2frame.PatternId, 'Instrument Parameters'))
3293    Substances = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,G2frame.PatternId, 'Substances'))
3294    ProfDict,Profile = G2frame.PatternTree.GetItemPyData(G2frame.PatternId)[:2]
3295    if data['BackFile']:
3296        BackId = G2gd.GetPatternTreeItemId(G2frame,G2frame.root,data['BackFile'])
3297        BackSample = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,BackId, 'Sample Parameters'))
3298        Profile[5] = BackSample['Scale'][0]*G2frame.PatternTree.GetItemPyData(BackId)[1][1]
3299    if G2frame.dataDisplay:
3300        G2frame.dataFrame.DestroyChildren()
3301    G2gd.SetDataMenuBar(G2frame,G2frame.dataFrame.ModelMenu)
3302    if not G2frame.dataFrame.GetStatusBar():
3303        Status = G2frame.dataFrame.CreateStatusBar()
3304    G2frame.dataFrame.SetLabel('Modelling')
3305    G2frame.dataDisplay = wxscroll.ScrolledPanel(G2frame.dataFrame)
3306    G2frame.dataFrame.Bind(wx.EVT_MENU, OnCopyModel, id=G2gd.wxID_MODELCOPY)
3307    G2frame.dataFrame.Bind(wx.EVT_MENU, OnCopyFlags, id=G2gd.wxID_MODELCOPYFLAGS)
3308    G2frame.dataFrame.Bind(wx.EVT_MENU, OnFitModel, id=G2gd.wxID_MODELFIT)
3309    G2frame.dataFrame.Bind(wx.EVT_MENU, OnFitModelAll, id=G2gd.wxID_MODELFITALL)
3310    G2frame.dataFrame.Bind(wx.EVT_MENU, OnUnDo, id=G2gd.wxID_MODELUNDO)
3311    G2frame.dataFrame.Bind(wx.EVT_MENU, OnAddModel, id=G2gd.wxID_MODELADD)
3312    Indx = {}
3313    mainSizer = wx.BoxSizer(wx.VERTICAL)
3314    topSizer = wx.BoxSizer(wx.HORIZONTAL)
3315    models = ['Size dist.','Particle fit']
3316    topSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Modeling by: '),0,WACV)
3317    fitSel = wx.ComboBox(G2frame.dataDisplay,value=data['Current'],choices=models,
3318        style=wx.CB_READONLY|wx.CB_DROPDOWN)
3319    fitSel.Bind(wx.EVT_COMBOBOX,OnSelectFit)       
3320    topSizer.Add(fitSel,0,WACV)
3321    topSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Error multiplier: '),0,WACV)
3322    esdScale = wx.TextCtrl(G2frame.dataDisplay,value='%.3f'%(1./np.sqrt(ProfDict['wtFactor'])),style=wx.TE_PROCESS_ENTER)
3323    esdScale.Bind(wx.EVT_TEXT_ENTER,OnEsdScale)       
3324    esdScale.Bind(wx.EVT_KILL_FOCUS,OnEsdScale)
3325    topSizer.Add(esdScale,0,WACV)
3326    mainSizer.Add(topSizer)
3327    G2gd.HorizontalLine(mainSizer,G2frame.dataDisplay)
3328    if 'Size' in data['Current']:
3329        if 'MaxEnt' in data['Size']['Method']:
3330            Status.SetStatusText('Size distribution by Maximum entropy')
3331        elif 'IPG' in data['Size']['Method']:
3332            Status.SetStatusText('Size distribution by Interior-Point Gradient')
3333        mainSizer.Add(SizeSizer())       
3334    elif 'Particle' in data['Current']:
3335        mainSizer.Add(PartSizer(),1,wx.ALIGN_LEFT|wx.EXPAND)
3336    G2gd.HorizontalLine(mainSizer,G2frame.dataDisplay)   
3337    backSizer = wx.BoxSizer(wx.HORIZONTAL)
3338    backSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Background:'),0,WACV)
3339    backVal = wx.TextCtrl(G2frame.dataDisplay,value='%.3g'%(data['Back'][0]),style=wx.TE_PROCESS_ENTER)
3340    Indx[backVal.GetId()] = ['Back',0,'%.3g']
3341    backVal.Bind(wx.EVT_TEXT_ENTER,OnBackChange)       
3342    backVal.Bind(wx.EVT_KILL_FOCUS,OnBackChange)
3343    backSizer.Add(backVal,0,WACV)
3344    backVar = wx.CheckBox(G2frame.dataDisplay,label='Refine?')
3345    Indx[backVar.GetId()] = [data['Back'],1]
3346    backVar.SetValue(data['Back'][1])
3347    backVar.Bind(wx.EVT_CHECKBOX, OnCheckBox)
3348    backSizer.Add(backVar,0,WACV)   
3349    backSizer.Add(wx.StaticText(G2frame.dataDisplay,-1,' Background file: '),0,WACV)
3350    Choices = ['',]+G2gd.GetPatternTreeDataNames(G2frame,['SASD',])
3351    backFile = wx.ComboBox(parent=G2frame.dataDisplay,value=data['BackFile'],choices=Choices,
3352        style=wx.CB_READONLY|wx.CB_DROPDOWN)
3353    backFile.Bind(wx.EVT_COMBOBOX,OnBackFile)
3354    backSizer.Add(backFile)   
3355    mainSizer.Add(backSizer)
3356
3357    mainSizer.Layout()   
3358    G2frame.dataDisplay.SetSizer(mainSizer)
3359    G2frame.dataDisplay.SetAutoLayout(1)
3360    G2frame.dataDisplay.SetupScrolling()
3361    Size = mainSizer.Fit(G2frame.dataFrame)
3362    Size[0] += 25
3363    G2frame.dataDisplay.SetSize(Size)
3364    G2frame.dataFrame.setSizePosLeft(Size)   
3365   
3366################################################################################
3367#####  PDF controls
3368################################################################################           
3369       
3370def UpdatePDFGrid(G2frame,data):
3371    '''respond to selection of PWDR PDF data tree item.
3372    '''
3373    global inst
3374    tth2q = lambda t,w:4.0*math.pi*sind(t/2.0)/w
3375    dataFile = G2frame.PatternTree.GetItemText(G2frame.PatternId)
3376    powName = 'PWDR'+dataFile[4:]
3377    powId = G2gd.GetPatternTreeItemId(G2frame,G2frame.root, powName)
3378    fullLimits,limits = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,powId, 'Limits'))[:2]
3379    inst = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,powId, 'Instrument Parameters'))[0]
3380    if 'Lam' in inst:
3381        keV = 12.397639/inst['Lam'][1]
3382    else:
3383        keV = 12.397639/inst['Lam1'][0]
3384    wave = 12.397639/keV
3385    qLimits = [tth2q(fullLimits[0],wave),tth2q(fullLimits[1],wave)]
3386    data['QScaleLim'][1] = min(qLimits[1],data['QScaleLim'][1])
3387    if data['QScaleLim'][0]:
3388        data['QScaleLim'][0] = max(qLimits[0],data['QScaleLim'][0])
3389    else:                                #initial setting at 90% of max Q
3390        data['QScaleLim'][0] = 0.90*data['QScaleLim'][1]
3391    polariz = inst['Polariz.'][1]
3392    azimuth = inst['Azimuth'][1]
3393    itemDict = {}
3394   
3395    def FillFileSizer(fileSizer,key):
3396        #fileSizer is a FlexGridSizer(3,6)
3397       
3398        def OnSelectFile(event):
3399            Obj = event.GetEventObject()
3400            fileKey,itemKey,fmt = itemDict[Obj.GetId()]
3401            if itemKey == 'Name':
3402                value = Obj.GetValue()
3403            Obj.SetValue(fmt%(value))
3404            data[fileKey][itemKey] = value
3405            UpdatePDFGrid(G2frame,data)
3406       
3407        def OnValueChange(event):
3408            Obj = event.GetEventObject()
3409            fileKey,itemKey,fmt = itemDict[Obj.GetId()]
3410            try:
3411                value = float(Obj.GetValue())
3412            except ValueError:
3413                value = -1.0
3414            Obj.SetValue(fmt%(value))
3415            data[fileKey][itemKey] = value
3416            auxPlot = ComputePDF(data)
3417            G2plt.PlotISFG(G2frame,newPlot=True)
3418                       
3419        item = data[key]
3420        fileList = np.array(GetFileList('PWDR')).T[1]
3421        fileSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' '+key+' file:'),0,WACV)
3422        fileName = wx.ComboBox(G2frame.dataDisplay,value=item['Name'],choices=fileList,
3423            style=wx.CB_READONLY|wx.CB_DROPDOWN)
3424        itemDict[fileName.GetId()] = [key,'Name','%s']
3425        fileName.Bind(wx.EVT_COMBOBOX,OnSelectFile)       
3426        fileSizer.Add(fileName,0,)
3427        fileSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label='Multiplier:'),0,WACV)
3428        mult = wx.TextCtrl(G2frame.dataDisplay,value='%.3f'%(item['Mult']),style=wx.TE_PROCESS_ENTER)
3429        itemDict[mult.GetId()] = [key,'Mult','%.3f']
3430        mult.Bind(wx.EVT_TEXT_ENTER,OnValueChange)       
3431        mult.Bind(wx.EVT_KILL_FOCUS,OnValueChange)
3432        fileSizer.Add(mult,0,)
3433        fileSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label='Add:'),0,WACV)
3434        add = wx.TextCtrl(G2frame.dataDisplay,value='%.0f'%(item['Add']),style=wx.TE_PROCESS_ENTER)
3435        itemDict[add.GetId()] = [key,'Add','%.0f']
3436        add.Bind(wx.EVT_TEXT_ENTER,OnValueChange)       
3437        add.Bind(wx.EVT_KILL_FOCUS,OnValueChange)
3438        fileSizer.Add(add,0,)
3439       
3440    def SumElementVolumes():
3441        sumVol = 0.
3442        ElList = data['ElList']
3443        for El in ElList:
3444            Avol = (4.*math.pi/3.)*ElList[El]['Drad']**3
3445            sumVol += Avol*ElList[El]['FormulaNo']
3446        return sumVol
3447        auxPlot = ComputePDF(data)
3448        G2plt.PlotISFG(G2frame,newPlot=True)       
3449       
3450    def FillElemSizer(elemSizer,ElData):
3451       
3452        def OnFractionChange(event):
3453            try:
3454                value = max(0.0,float(num.GetValue()))
3455            except ValueError:
3456                value = 0.0
3457            num.SetValue('%.3f'%(value))
3458            ElData['FormulaNo'] = value
3459            data['Form Vol'] = max(10.0,SumElementVolumes())
3460            formVol.SetValue('%.2f'%(data['Form Vol']))
3461            wx.CallAfter(UpdatePDFGrid,G2frame,data)
3462            auxPlot = ComputePDF(data)
3463            G2plt.PlotISFG(G2frame,newPlot=True)       
3464       
3465        elemSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,
3466            label=' Element: '+'%2s'%(ElData['Symbol'])+' * '),0,WACV)
3467        num = wx.TextCtrl(G2frame.dataDisplay,value='%.3f'%(ElData['FormulaNo']),style=wx.TE_PROCESS_ENTER)
3468        num.Bind(wx.EVT_TEXT_ENTER,OnFractionChange)       
3469        num.Bind(wx.EVT_KILL_FOCUS,OnFractionChange)
3470        elemSizer.Add(num,0,WACV)
3471        elemSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,
3472            label="f': %.3f"%(ElData['fp'])+' f": %.3f'%(ElData['fpp'])+' mu: %.2f barns'%(ElData['mu']) ),
3473            0,WACV)
3474           
3475    def OnGeometry(event):
3476        data['Geometry'] = geometry.GetValue()
3477        UpdatePDFGrid(G2frame,data)
3478        auxPlot = ComputePDF(data)
3479        G2plt.PlotISFG(G2frame,newPlot=True)       
3480       
3481    def OnDetType(event):
3482        data['DetType'] = detType.GetValue()
3483        UpdatePDFGrid(G2frame,data)
3484        auxPlot = ComputePDF(data)
3485        G2plt.PlotISFG(G2frame,newPlot=True)       
3486       
3487    def OnFormVol(event):
3488        try:
3489            value = float(formVol.GetValue())
3490            if value <= 0.0:
3491                raise ValueError
3492        except ValueError:
3493            value = data['Form Vol']
3494        data['Form Vol'] = value
3495        UpdatePDFGrid(G2frame,data)
3496        auxPlot = ComputePDF(data)
3497        G2plt.PlotISFG(G2frame,newPlot=False)       
3498       
3499    def OnDiameter(event):
3500        try:
3501            value = float(diam.GetValue())
3502            if value <= 0.0:
3503                raise ValueError
3504        except ValueError:
3505            value = data['Diam']
3506        data['Diam'] = value
3507        UpdatePDFGrid(G2frame,data)
3508        auxPlot = ComputePDF(data)
3509        G2plt.PlotISFG(G2frame,newPlot=False)
3510       
3511    def OnPolaVal(event):
3512        try:
3513            value = float(polaVal.GetValue())
3514            if not (0.0 <= value <= 1.0):
3515                raise ValueError
3516        except ValueError:
3517            value = inst['Polariz.'][1]
3518        inst['Polariz.'][1] = value
3519        polaVal.SetValue('%.2f'%(inst['Polariz.'][1]))
3520        UpdatePDFGrid(G2frame,data)
3521        auxPlot = ComputePDF(data)
3522        G2plt.PlotISFG(G2frame,newPlot=False)
3523               
3524    def OnAzimVal(event):
3525        try:
3526            value = float(azimVal.GetValue())
3527            if not (0. <= value <= 360.):
3528                raise ValueError
3529        except ValueError:
3530            value = inst['Azimuth'][1]
3531        inst['Azimuth'][1] = value
3532        azimVal.SetValue('%.1f'%(inst['Azimuth'][1]))
3533        UpdatePDFGrid(G2frame,data)
3534        auxPlot = ComputePDF(data)
3535        G2plt.PlotISFG(G2frame,newPlot=False)
3536                       
3537    def OnObliqCoeff(event):
3538        try:
3539            value = float(obliqCoeff.GetValue())
3540            if value < 0.0:
3541                raise ValueError
3542            elif value > 1.0:
3543                value = 1.0
3544        except ValueError:
3545            value = data['ObliqCoeff']
3546        data['ObliqCoeff'] = value
3547        obliqCoeff.SetValue('%.3f'%(value))
3548        auxPlot = ComputePDF(data)
3549        G2plt.PlotISFG(G2frame,newPlot=False)
3550       
3551    def OnRulandWdt(event):
3552        try:
3553            value = float(rulandWdt.GetValue())
3554            if value <= 0.001:
3555                raise ValueError
3556            elif value > 1.0:
3557                value = 1.0
3558        except ValueError:
3559            value = data['Ruland']
3560        data['Ruland'] = value
3561        rulandWdt.SetValue('%.3f'%(value))
3562        auxPlot = ComputePDF(data)
3563        G2plt.PlotISFG(G2frame,newPlot=False)
3564       
3565    def OnRulSlider(event):
3566        value = int(rulandSldr.GetValue())/1000.
3567        data['Ruland'] = max(0.001,value)
3568        rulandWdt.SetValue('%.3f'%(data['Ruland']))
3569        auxPlot = ComputePDF(data)
3570        G2plt.PlotISFG(G2frame,newPlot=False)
3571       
3572    def OnLorch(event):
3573        data['Lorch'] = lorch.GetValue()
3574        auxPlot = ComputePDF(data)
3575        G2plt.PlotISFG(G2frame,newPlot=False)       
3576                       
3577    def OnPacking(event):
3578        try:
3579            value = float(pack.GetValue())
3580            if value <= 0.0:
3581                raise ValueError
3582        except ValueError:
3583            value = data['Pack']
3584        data['Pack'] = value
3585        UpdatePDFGrid(G2frame,data)
3586        auxPlot = ComputePDF(data)
3587        G2plt.PlotISFG(G2frame,newPlot=False)       
3588               
3589    def OnSQmin(event):
3590        try:
3591            value = float(SQmin.GetValue())
3592            if value < qLimits[0]:
3593                raise ValueError
3594        except ValueError:
3595            value = max(qLimits[0],data['QScaleLim'][0])
3596        data['QScaleLim'][0] = value
3597        SQmin.SetValue('%.1f'%(value))
3598        auxPlot = ComputePDF(data)
3599        G2plt.PlotISFG(G2frame,newPlot=True)       
3600       
3601    def OnSQmax(event):
3602        try:
3603            value = float(SQmax.GetValue())
3604            if value > qLimits[1]:
3605                raise ValueError
3606        except ValueError:
3607            value = min(qLimits[1],data['QScaleLim'][1])
3608        data['QScaleLim'][1] = value
3609        if value < data['QScaleLim'][0]:
3610            data['QScaleLim'][0] = 0.90*value
3611            SQmin.SetValue('%.1f'%(data['QScaleLim'][0]))
3612        SQmax.SetValue('%.1f'%(value))
3613        auxPlot = ComputePDF(data)
3614        G2plt.PlotISFG(G2frame,newPlot=True)
3615       
3616    def OnResetQ(event):
3617        resetQ.SetValue(False)
3618        data['QScaleLim'][1] = qLimits[1]
3619        SQmax.SetValue('%.1f'%(data['QScaleLim'][1]))
3620        data['QScaleLim'][0] = 0.9*qLimits[1]
3621        SQmin.SetValue('%.1f'%(data['QScaleLim'][0]))
3622        auxPlot = ComputePDF(data)
3623        G2plt.PlotISFG(G2frame,newPlot=True)       
3624
3625    def GetFileList(fileType,skip=None):
3626        fileList = [[False,'',0]]
3627        Source = ''
3628        id, cookie = G2frame.PatternTree.GetFirstChild(G2frame.root)
3629        while id:
3630            name = G2frame.PatternTree.GetItemText(id)
3631            if fileType in name:
3632                if id == skip:
3633                    Source = name
3634                else:
3635                    fileList.append([False,name,id])
3636            id, cookie = G2frame.PatternTree.GetNextChild(G2frame.root, cookie)
3637        if skip:
3638            return fileList,Source
3639        else:
3640            return fileList
3641       
3642    def OnCopyPDFControls(event):
3643        import copy
3644        TextList,Source = GetFileList('PDF',skip=G2frame.PatternId)
3645        TextList[0] = [False,'All PDF',0]
3646        if len(TextList) == 1:
3647            G2frame.ErrorDialog('Nothing to copy controls to','There must be more than one "PDF" pattern')
3648            return
3649        dlg = G2frame.CopyDialog(G2frame,'Copy PDF controls','Copy controls from '+Source+' to:',TextList)
3650        try:
3651            if dlg.ShowModal() == wx.ID_OK:
3652                result = dlg.GetData()
3653                if result[0][0]:
3654                    result = TextList[1:]
3655                    for item in result: item[0] = True
3656                for i,item in enumerate(result):
3657                    ifcopy,name,id = item
3658                    if ifcopy:
3659                        olddata = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,id, 'PDF Controls'))
3660                        sample = olddata['Sample']
3661                        olddata.update(copy.deepcopy(data))
3662                        olddata['Sample'] = sample
3663                        G2frame.PatternTree.SetItemPyData(G2gd.GetPatternTreeItemId(G2frame,id, 'PDF Controls'),olddata)
3664                Status.SetStatusText('PDF controls copied')
3665        finally:
3666            dlg.Destroy()
3667               
3668    def OnSavePDFControls(event):
3669        print 'save PDF controls?'
3670       
3671    def OnLoadPDFControls(event):
3672        print 'Load PDF controls?'
3673       
3674    def OnAddElement(event):
3675        ElList = data['ElList']
3676        PE = G2elemGUI.PickElement(G2frame,oneOnly=True)
3677        if PE.ShowModal() == wx.ID_OK:
3678            El = PE.Elem
3679            if El not in ElList and El != 'None':
3680                ElemSym = El.strip().upper()               
3681                FpMu = G2elem.FPcalc(G2elem.GetXsectionCoeff(ElemSym), keV)
3682                ElData = G2elem.GetFormFactorCoeff(ElemSym)[0]
3683                ElData['FormulaNo'] = 0.0
3684                ElData.update(G2elem.GetAtomInfo(ElemSym))
3685                ElData.update(dict(zip(['fp','fpp','mu'],FpMu)))
3686                ElData.update(G2elem.GetFFC5(El))
3687                data['ElList'][El] = ElData
3688            data['Form Vol'] = max(10.0,SumElementVolumes())
3689        PE.Destroy()
3690        UpdatePDFGrid(G2frame,data)
3691       
3692    def OnDeleteElement(event):
3693        ElList = data['ElList']
3694        choice = ElList.keys()
3695        dlg = G2elemGUI.DeleteElement(G2frame,choice=choice)
3696        if dlg.ShowModal() == wx.ID_OK:
3697            del ElList[dlg.GetDeleteElement()]
3698        dlg.Destroy()
3699        UpdatePDFGrid(G2frame,data)
3700               
3701    def ComputePDF(Data):
3702        xydata = {}
3703        for key in ['Sample','Sample Bkg.','Container','Container Bkg.']:
3704            name = Data[key]['Name']
3705            if name:
3706                xydata[key] = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,G2frame.root,name))
3707                PDFname = name
3708        powName = xydata['Sample'][2]
3709        powId = G2gd.GetPatternTreeItemId(G2frame,G2frame.root,powName)
3710        inst = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,powId,'Instrument Parameters'))[0]
3711        auxPlot = G2pwd.CalcPDF(Data,inst,xydata)
3712        PDFId = G2gd.GetPatternTreeItemId(G2frame,G2frame.root,'PDF '+powName[4:])
3713        G2frame.PatternTree.SetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PDFId,'I(Q)'+powName[4:]),xydata['IofQ'])
3714        G2frame.PatternTree.SetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PDFId,'S(Q)'+powName[4:]),xydata['SofQ'])
3715        G2frame.PatternTree.SetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PDFId,'F(Q)'+powName[4:]),xydata['FofQ'])
3716        G2frame.PatternTree.SetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PDFId,'G(R)'+powName[4:]),xydata['GofR'])
3717        return auxPlot
3718       
3719    def OnComputePDF(event):
3720        print 'Calculating PDF:'
3721        auxPlot = ComputePDF(data)
3722        print 'Done calculating PDF:'
3723        Status.SetStatusText('PDF computed')
3724        for plot in auxPlot:
3725            G2plt.PlotXY(G2frame,plot[:2],type=plot[2])
3726       
3727        G2plt.PlotISFG(G2frame,newPlot=True,type='I(Q)')
3728        G2plt.PlotISFG(G2frame,newPlot=True,type='S(Q)')
3729        G2plt.PlotISFG(G2frame,newPlot=True,type='F(Q)')
3730        G2plt.PlotISFG(G2frame,newPlot=True,type='G(R)')
3731       
3732    def OnComputeAllPDF(event):
3733        print 'Calculating PDFs:'
3734        if G2frame.PatternTree.GetCount():
3735            id, cookie = G2frame.PatternTree.GetFirstChild(G2frame.root)
3736            while id:
3737                Name = G2frame.PatternTree.GetItemText(id)
3738                if 'PDF' in Name:
3739                    Data = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,id,'PDF Controls'))
3740                    auxPlot = ComputePDF(Data)                   
3741                id, cookie = G2frame.PatternTree.GetNextChild(G2frame.root, cookie)
3742            Status.SetStatusText('All PDFs computed')
3743            G2plt.PlotISFG(G2frame,newPlot=True,type='G(R)')
3744            print ' Done calculating PDFs:'
3745       
3746    def OnShowTip(G2frame,tip):
3747        print tip   
3748               
3749    if G2frame.dataDisplay:
3750        G2frame.dataFrame.Clear()
3751    G2gd.SetDataMenuBar(G2frame,G2frame.dataFrame.PDFMenu)
3752    if not G2frame.dataFrame.GetStatusBar():
3753        Status = G2frame.dataFrame.CreateStatusBar()   
3754    G2frame.dataDisplay = wx.Panel(G2frame.dataFrame)
3755    G2frame.dataFrame.Bind(wx.EVT_MENU, OnCopyPDFControls, id=G2gd.wxID_PDFCOPYCONTROLS)
3756    G2frame.dataFrame.Bind(wx.EVT_MENU, OnSavePDFControls, id=G2gd.wxID_PDFSAVECONTROLS)
3757    G2frame.dataFrame.Bind(wx.EVT_MENU, OnLoadPDFControls, id=G2gd.wxID_PDFLOADCONTROLS)
3758    G2frame.dataFrame.Bind(wx.EVT_MENU, OnAddElement, id=G2gd.wxID_PDFADDELEMENT)
3759    G2frame.dataFrame.Bind(wx.EVT_MENU, OnDeleteElement, id=G2gd.wxID_PDFDELELEMENT)
3760    G2frame.dataFrame.Bind(wx.EVT_MENU, OnComputePDF, id=G2gd.wxID_PDFCOMPUTE)
3761    G2frame.dataFrame.Bind(wx.EVT_MENU, OnComputeAllPDF, id=G2gd.wxID_PDFCOMPUTEALL)
3762    mainSizer = wx.BoxSizer(wx.VERTICAL)
3763    mainSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' PDF data files: '),0,WACV)
3764    mainSizer.Add((5,5),0)
3765    str = ' Sample file: PWDR %s   Wavelength, A: %.5f  Energy, keV: %.3f  Polariz.: %.2f '%(dataFile[3:],wave,keV,polariz)
3766    mainSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=str),0,WACV)
3767#    dataSizer = wx.BoxSizer(wx.HORIZONTAL)
3768#    dataSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label='Azimuth'),0,WACV)
3769#    azimVal = wx.TextCtrl(G2frame.dataDisplay,value='%.2f'%(inst['Azimuth']))
3770#    azimVal.Bind(wx.EVT_TEXT_ENTER,OnAzimVal)       
3771#    azimVal.Bind(wx.EVT_KILL_FOCUS,OnAzimVal)
3772#    dataSizer.Add(azimVal,0)   
3773#    dataSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label='Polarization'),0,WACV)
3774#    polaVal = wx.TextCtrl(G2frame.dataDisplay,value='%.2f'%(inst['Polariz.']))
3775#    polaVal.Bind(wx.EVT_TEXT_ENTER,OnPolaVal)       
3776#    polaVal.Bind(wx.EVT_KILL_FOCUS,OnPolaVal)
3777#    dataSizer.Add(polaVal,0)   
3778#    mainSizer.Add(dataSizer,0)
3779    mainSizer.Add((5,5),0)
3780    fileSizer = wx.FlexGridSizer(3,6,5,1)
3781    select = ['Sample Bkg.','Container']
3782    if data['Container']['Name']:
3783        select.append('Container Bkg.')
3784    for key in select:
3785        FillFileSizer(fileSizer,key)
3786    mainSizer.Add(fileSizer,0)
3787    mainSizer.Add((5,5),0)
3788    mainSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Sample information: '),0,WACV)
3789    mainSizer.Add((5,5),0)   
3790
3791    ElList = data['ElList']
3792    Abs = G2lat.CellAbsorption(ElList,data['Form Vol'])
3793    Trans = G2pwd.Transmission(data['Geometry'],Abs*data['Pack'],data['Diam'])
3794    elemSizer = wx.FlexGridSizer(3,3,5,1)
3795    for El in ElList:
3796        FillElemSizer(elemSizer,ElList[El])
3797    mainSizer.Add(elemSizer,0)
3798    mainSizer.Add((5,5),0)   
3799    midSizer = wx.BoxSizer(wx.HORIZONTAL)
3800    midSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Formula volume: '),0,WACV)
3801    formVol = wx.TextCtrl(G2frame.dataDisplay,value='%.2f'%(data['Form Vol']))
3802    formVol.Bind(wx.EVT_TEXT_ENTER,OnFormVol)       
3803    formVol.Bind(wx.EVT_KILL_FOCUS,OnFormVol)
3804    midSizer.Add(formVol,0)
3805    midSizer.Add(wx.StaticText(G2frame.dataDisplay,
3806        label=' Theoretical absorption: %.4f cm-1 Sample absorption: %.4f cm-1'%(Abs,Abs*data['Pack'])),
3807        0,WACV)
3808    mainSizer.Add(midSizer,0)
3809    mainSizer.Add((5,5),0)   
3810
3811    geoBox = wx.BoxSizer(wx.HORIZONTAL)
3812    geoBox.Add(wx.StaticText(G2frame.dataDisplay,label=' Sample geometry: '),0,WACV)
3813    choice = ['Cylinder','Bragg-Brentano','Tilting flat plate in transmission','Fixed flat plate']
3814    geometry = wx.ComboBox(G2frame.dataDisplay,value=data['Geometry'],choices=choice,
3815            style=wx.CB_READONLY|wx.CB_DROPDOWN)
3816    geometry.Bind(wx.EVT_COMBOBOX, OnGeometry)
3817    geoBox.Add(geometry,0)
3818    geoBox.Add(wx.StaticText(G2frame.dataDisplay,label=' Sample diameter/thickness, mm: '),0,WACV)
3819    diam = wx.TextCtrl(G2frame.dataDisplay,value='%.3f'%(data['Diam']))
3820    diam.Bind(wx.EVT_TEXT_ENTER,OnDiameter)       
3821    diam.Bind(wx.EVT_KILL_FOCUS,OnDiameter)
3822#    diam.Bind(wx.EVT_SET_FOCUS,OnShowTip(G2frame,'tip')) #this doesn't work - what would????
3823    geoBox.Add(diam,0)
3824    mainSizer.Add(geoBox,0)
3825    mainSizer.Add((5,5),0)   
3826    geoBox = wx.BoxSizer(wx.HORIZONTAL)
3827    geoBox.Add(wx.StaticText(G2frame.dataDisplay,label=' Packing: '),0,WACV)
3828    pack = wx.TextCtrl(G2frame.dataDisplay,value='%.2f'%(data['Pack']))
3829    pack.Bind(wx.EVT_TEXT_ENTER,OnPacking)       
3830    pack.Bind(wx.EVT_KILL_FOCUS,OnPacking)
3831    geoBox.Add(pack,0)
3832    geoBox.Add(wx.StaticText(G2frame.dataDisplay,label=' Sample transmission: %.3f %%'%(Trans)),0,WACV)   
3833    mainSizer.Add(geoBox,0)
3834    mainSizer.Add((5,5),0)   
3835       
3836    mainSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' S(Q)->F(Q)->G(R) controls: '),0,WACV)
3837    mainSizer.Add((5,5),0)
3838    sqBox = wx.BoxSizer(wx.HORIZONTAL)
3839    sqBox.Add(wx.StaticText(G2frame.dataDisplay,label=' Detector type: '),0,WACV)
3840    choice = ['Image plate','Point detector']
3841    detType = wx.ComboBox(G2frame.dataDisplay,value=data['DetType'],choices=choice,
3842            style=wx.CB_READONLY|wx.CB_DROPDOWN)
3843    detType.Bind(wx.EVT_COMBOBOX, OnDetType)
3844    sqBox.Add(detType,0)
3845    if data['DetType'] == 'Image plate':
3846        sqBox.Add(wx.StaticText(G2frame.dataDisplay,label=' IP transmission coeff.: '),0,WACV)
3847        obliqCoeff = wx.TextCtrl(G2frame.dataDisplay,value='%.3f'%(data['ObliqCoeff']))
3848        obliqCoeff.Bind(wx.EVT_TEXT_ENTER,OnObliqCoeff)       
3849        obliqCoeff.Bind(wx.EVT_KILL_FOCUS,OnObliqCoeff)
3850        sqBox.Add(obliqCoeff,0)
3851    mainSizer.Add(sqBox,0)
3852       
3853    sqBox = wx.BoxSizer(wx.HORIZONTAL)
3854    sqBox.Add(wx.StaticText(G2frame.dataDisplay,label=' Ruland width: '),0,WACV)   
3855    rulandSldr = wx.Slider(parent=G2frame.dataDisplay,style=wx.SL_HORIZONTAL,
3856        value=int(1000*data['Ruland']))
3857    sqBox.Add(rulandSldr,1,wx.EXPAND)
3858    rulandSldr.Bind(wx.EVT_SLIDER, OnRulSlider)
3859    rulandWdt = wx.TextCtrl(G2frame.dataDisplay,value='%.3f'%(data['Ruland']))
3860    rulandWdt.Bind(wx.EVT_TEXT_ENTER,OnRulandWdt)       
3861    rulandWdt.Bind(wx.EVT_KILL_FOCUS,OnRulandWdt)
3862    sqBox.Add(rulandWdt,0,WACV)   
3863    mainSizer.Add(sqBox,0,wx.ALIGN_LEFT|wx.EXPAND)
3864   
3865    sqBox = wx.BoxSizer(wx.HORIZONTAL)
3866    lorch = wx.CheckBox(parent=G2frame.dataDisplay,label='Lorch damping?')
3867    lorch.SetValue(data['Lorch'])
3868    lorch.Bind(wx.EVT_CHECKBOX, OnLorch)
3869    sqBox.Add(lorch,0,WACV)
3870    sqBox.Add(wx.StaticText(G2frame.dataDisplay,label=' Scaling q-range: '),0,WACV)
3871    SQmin = wx.TextCtrl(G2frame.dataDisplay,value='%.1f'%(data['QScaleLim'][0]))
3872    SQmin.Bind(wx.EVT_TEXT_ENTER,OnSQmin)       
3873    SQmin.Bind(wx.EVT_KILL_FOCUS,OnSQmin)   
3874    sqBox.Add(SQmin,0)
3875    sqBox.Add(wx.StaticText(G2frame.dataDisplay,label=' to '),0,WACV)
3876    SQmax = wx.TextCtrl(G2frame.dataDisplay,value='%.1f'%(data['QScaleLim'][1]))
3877    SQmax.Bind(wx.EVT_TEXT_ENTER,OnSQmax)       
3878    SQmax.Bind(wx.EVT_KILL_FOCUS,OnSQmax)
3879    sqBox.Add(SQmax,0)
3880    resetQ = wx.CheckBox(parent=G2frame.dataDisplay,label='Reset?')
3881    sqBox.Add(resetQ,0)
3882    resetQ.Bind(wx.EVT_CHECKBOX, OnResetQ)
3883   
3884    mainSizer.Add(sqBox,0)
3885
3886    mainSizer.Layout()   
3887    G2frame.dataDisplay.SetSizer(mainSizer)
3888    Size = mainSizer.Fit(G2frame.dataFrame)
3889    G2frame.dataDisplay.SetSize(Size)
3890    G2frame.dataFrame.setSizePosLeft(Size)
3891   
Note: See TracBrowser for help on using the repository browser.