source: trunk/GSASIIpwdGUI.py @ 1475

Last change on this file since 1475 was 1475, checked in by vondreele, 11 years ago

add MCSA tutorial to main gsasII.html web page
change difB tern from d3 to 1/d - works much better
make all TOF/2-theta to dsp & vv conversions with G2lat.Pos2dsp & Dsp2pos routines.

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