source: branch/logging/GSASIIpwdGUI.py @ 1477

Last change on this file since 1477 was 1477, checked in by toby, 7 years ago

variable change logging finally works

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