source: trunk/GSASIIpwdGUI.py @ 1313

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

fix contrast calculation for sasd.
put in a wx.CallAfter?

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