source: trunk/GSASIIpwdGUI.py @ 1443

Last change on this file since 1443 was 1443, checked in by vondreele, 7 years ago

add calibration of lam, difC, etc. from index peak positions
new plotCalib routine

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