source: trunk/GSASIIpwdGUI.py @ 1328

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

fix Copy Flags for SASD Models - it wasn't doing structure factor parms.

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