source: trunk/GSASIIpwdGUI.py @ 1459

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

add instrument parameters (flight path & detector 2-theta) needed for TOF
rework reflection list for TOF
change default diff curve & reflection marker offsets
change weighting to instrument constants calibration to be 1/esd2 from peak fit positions - works a lot better
1st shot at TOF Rietveld refinement with derivatives - need to be checked for correctness (some are wrong)

  • Property svn:eol-style set to native
  • Property svn:keywords set to Date Author Revision URL Id
File size: 190.2 KB
Line 
1# -*- coding: utf-8 -*-
2#GSASIIpwdGUI - powder data display routines
3########### SVN repository information ###################
4# $Date: 2014-08-08 19:59:09 +0000 (Fri, 08 Aug 2014) $
5# $Author: vondreele $
6# $Revision: 1459 $
7# $URL: trunk/GSASIIpwdGUI.py $
8# $Id: GSASIIpwdGUI.py 1459 2014-08-08 19:59:09Z 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: 1459 $")
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-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                inst = G2IO.makeInstDict(newItems,newVals,len(newVals)*[False,])
1010                G2frame.PatternTree.SetItemPyData(G2gd.GetPatternTreeItemId(G2frame,G2frame.PatternId,'Instrument Parameters'),[inst,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','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-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 OnCellChange(event):
2016        ibrav = bravaisSymb.index(controls[5])
2017        Obj = event.GetEventObject()
2018        ObjId = cellList.index(Obj.GetId())
2019        try:
2020            value = max(1.0,float(Obj.GetValue()))
2021        except ValueError:
2022            if ObjId < 3:               #bad cell edge - reset
2023                value = controls[6+ObjId]
2024            else:                       #bad angle
2025                value = 90.
2026        if ibrav in [0,1,2]:
2027            controls[6] = controls[7] = controls[8] = value
2028            controls[9] = controls[10] = controls[11] = 90.0
2029            Obj.SetValue("%.5f"%(controls[6]))
2030        elif ibrav in [3,4,5,6]:
2031            if ObjId == 0:
2032                controls[6] = controls[7] = value
2033                Obj.SetValue("%.5f"%(controls[6]))
2034            else:
2035                controls[8] = value
2036                Obj.SetValue("%.5f"%(controls[8]))
2037            controls[9] = controls[10] = controls[11] = 90.0
2038            if ibrav in [3,4]:
2039                controls[11] = 120.
2040        elif ibrav in [7,8,9,10]:
2041            controls[6+ObjId] = value
2042            Obj.SetValue("%.5f"%(controls[6+ObjId]))
2043            controls[9] = controls[10] = controls[11] = 90.0
2044        elif ibrav in [11,12]:
2045            controls[9] = controls[11] = 90.0
2046            if ObjId != 3:
2047                controls[6+ObjId] = value
2048                Obj.SetValue("%.5f"%(controls[6+ObjId]))
2049            else:
2050                controls[10] = value
2051                Obj.SetValue("%.3f"%(controls[10]))
2052        else:
2053            controls[6+ObjId] = value
2054            if ObjId < 3:
2055                Obj.SetValue("%.5f"%(controls[6+ObjId]))
2056            else:
2057                Obj.SetValue("%.3f"%(controls[6+ObjId]))
2058        controls[12] = G2lat.calc_V(G2lat.cell2A(controls[6:12]))
2059        volVal.SetValue("%.3f"%(controls[12]))
2060       
2061    def OnHklShow(event):
2062        PatternId = G2frame.PatternId
2063        PickId = G2frame.PickId   
2064        peaks = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId, 'Index Peak List'))[0]
2065        limits = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId, 'Limits'))[1]
2066        controls,bravais,cells,dmin = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId, 'Unit Cells List'))
2067        cell = controls[6:12]
2068        A = G2lat.cell2A(cell)
2069        ibrav = bravaisSymb.index(controls[5])
2070        spc = controls[13]
2071        SGData = G2spc.SpcGroup(spc)[1]
2072        if 'C' in Inst['Type'][0]:
2073            dmin = G2lat.Pos2dsp(Inst,limits[1])
2074        else:   #TOF - use other limit!
2075            dmin = G2lat.Pos2dsp(Inst,limits[0])
2076        G2frame.HKL = G2pwd.getHKLpeak(dmin,SGData,A)
2077        G2indx.IndexPeaks(peaks,G2frame.HKL)
2078        for hkl in G2frame.HKL:
2079            hkl.append(G2lat.Dsp2pos(Inst,hkl[3])++controls[1])
2080        if 'PKS' in G2frame.PatternTree.GetItemText(G2frame.PatternId):
2081            G2plt.PlotPowderLines(G2frame)
2082        else:
2083            G2plt.PlotPatterns(G2frame)
2084           
2085    def OnSortCells(event):
2086        controls,bravais,cells,dmin = G2frame.PatternTree.GetItemPyData(UnitCellsId)
2087        c =  event.GetCol()
2088        if colLabels[c] == 'M20':
2089            cells = G2indx.sortM20(cells)
2090        elif colLabels[c] == 'Volume':
2091            cells = G2indx.sortVolume(cells)
2092        else:
2093            return
2094        data = [controls,bravais,cells,dmin]
2095        G2frame.PatternTree.SetItemPyData(UnitCellsId,data)
2096        wx.CallAfter(UpdateUnitCellsGrid,G2frame,data)
2097       
2098    def CopyUnitCell(event):
2099        controls,bravais,cells,dmin = G2frame.PatternTree.GetItemPyData(UnitCellsId)
2100        for Cell in cells:
2101            if Cell[-2]:
2102                break
2103        cell = Cell[2:9]
2104        controls[4] = 1
2105        controls[5] = bravaisSymb[cell[0]]
2106        controls[6:12] = cell[1:8]
2107        controls[12] = G2lat.calc_V(G2lat.cell2A(controls[6:12]))
2108        controls[13] = spaceGroups[bravaisSymb.index(controls[5])]
2109        G2frame.PatternTree.SetItemPyData(UnitCellsId,[controls,bravais,cells,dmin])
2110        G2frame.dataFrame.RefineCell.Enable(True)
2111        wx.CallAfter(UpdateUnitCellsGrid,G2frame,data)       
2112               
2113    def RefineCell(event):
2114        def cellPrint(ibrav,A):
2115            cell = G2lat.A2cell(A)
2116            Vol = G2lat.calc_V(A)
2117            if ibrav in [0,1,2]:
2118                print "%s%10.6f" % ('a =',cell[0])
2119            elif ibrav in [3,4,5,6]:
2120                print "%s%10.6f %s%10.6f %s%12.3f" % ('a =',cell[0],' c =',cell[2],' volume =',Vol)
2121            elif ibrav in [7,8,9,10]:
2122                print "%s%10.6f %s%10.6f %s%10.6f %s%12.3f" % ('a =',cell[0],'b =',cell[1],'c =',cell[2],' volume =',Vol)
2123            elif ibrav in [11,12]:
2124                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)
2125            else:
2126                print "%s%10.6f %s%10.6f %s%10.6f" % ('a =',cell[0],'b =',cell[1],'c =',cell[2])
2127                print "%s%8.3f %s%8.3f %s%8.3f %s%12.3f" % ('alpha =',cell[3],'beta =',cell[4],'gamma =',cell[5],' volume =',Vol)
2128             
2129        PatternId = G2frame.PatternId
2130        PickId = G2frame.PickId   
2131        peaks = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId, 'Index Peak List'))
2132        if not peaks[0]:
2133            G2frame.ErrorDialog('No peaks!', 'Nothing to refine!')
2134            return       
2135        print 'Refine cell'
2136        controls,bravais,cells,dmin = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId, 'Unit Cells List'))
2137        cell = controls[6:12]
2138        A = G2lat.cell2A(cell)
2139        ibrav = bravaisSymb.index(controls[5])
2140        SGData = G2spc.SpcGroup(controls[13])[1]
2141        dmin = G2indx.getDmin(peaks[0])-0.005
2142        G2frame.HKL = G2pwd.getHKLpeak(dmin,SGData,A)
2143        G2indx.IndexPeaks(peaks[0],G2frame.HKL)
2144        if 'C' in Inst['Type'][0]:
2145            Lhkl,M20,X20,Aref,Zero = G2indx.refinePeaksZ(peaks[0],wave,ibrav,A,controls[1],controls[0])
2146        else:   #'T'OF
2147            Lhkl,M20,X20,Aref,Zero = G2indx.refinePeaksT(peaks[0],difC,ibrav,A,controls[1],controls[0])           
2148        controls[1] = Zero
2149        controls[6:12] = G2lat.A2cell(Aref)
2150        controls[12] = G2lat.calc_V(Aref)
2151        data = [controls,bravais,cells,dmin]
2152        cells = G2frame.PatternTree.GetItemPyData(UnitCellsId)[2]
2153        for cell in cells:
2154            cell[-2] = False
2155        cells.insert(0,[M20,X20,ibrav]+controls[6:13]+[True,False])
2156        data[2] = cells
2157        G2frame.PatternTree.SetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId, 'Unit Cells List'),data)
2158        G2frame.HKL = G2lat.GenHBravais(dmin,ibrav,Aref)
2159        print "%s%10.3f" % ('refinement M20 = ',M20)
2160        print 'unindexed lines = ',X20
2161        cellPrint(ibrav,Aref)
2162        for hkl in G2frame.HKL:
2163            hkl.append(G2lat.Dsp2pos(Inst,hkl[3])+controls[1])
2164        if 'PKS' in G2frame.PatternTree.GetItemText(G2frame.PatternId):
2165            G2plt.PlotPowderLines(G2frame)
2166        else:
2167            G2plt.PlotPatterns(G2frame)
2168        wx.CallAfter(UpdateUnitCellsGrid,G2frame,data)
2169       
2170    def IndexPeaks(event):
2171        PatternId = G2frame.PatternId   
2172        print 'Peak Indexing'
2173        keepcells = []
2174        try:
2175            controls,bravais,cells,dmin = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId, 'Unit Cells List'))
2176            for cell in cells:
2177                if cell[11]:
2178                    keepcells.append(cell)
2179        except IndexError:
2180            pass
2181        except ValueError:
2182            G2frame.ErrorDialog('Error','Need to set controls in Unit Cell List first')
2183            return
2184        if True not in bravais:
2185            G2frame.ErrorDialog('Error','No Bravais lattices selected')
2186            return
2187        G2frame.dataFrame.CopyCell.Enable(False)
2188        G2frame.dataFrame.RefineCell.Enable(False)
2189        OK,dmin,newcells = G2indx.DoIndexPeaks(peaks[0],controls,bravais)
2190        cells = keepcells+newcells
2191        cells = G2indx.sortM20(cells)
2192        cells[0][10] = True
2193        if OK:
2194            data = [controls,bravais,cells,dmin]
2195            G2frame.PatternTree.SetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId, 'Unit Cells List'),data)
2196            bestCell = cells[0]
2197            if bestCell[0] > 10.:
2198                G2frame.HKL = G2lat.GenHBravais(dmin,bestCell[2],G2lat.cell2A(bestCell[3:9]))
2199                for hkl in G2frame.HKL:
2200                    hkl.append(G2lat.Dsp2pos(Inst,hkl[3])+controls[1])
2201                if 'PKS' in G2frame.PatternTree.GetItemText(G2frame.PatternId):
2202                    G2plt.PlotPowderLines(G2frame)
2203                else:
2204                    G2plt.PlotPatterns(G2frame)
2205            G2frame.dataFrame.CopyCell.Enable(True)
2206            G2frame.dataFrame.IndexPeaks.Enable(True)
2207            G2frame.dataFrame.MakeNewPhase.Enable(True)
2208        wx.CallAfter(UpdateUnitCellsGrid,G2frame,data)
2209               
2210    def RefreshUnitCellsGrid(event):
2211        data =G2frame.PatternTree.GetItemPyData(UnitCellsId)
2212        cells,dmin = data[2:]
2213        r,c =  event.GetRow(),event.GetCol()
2214        if cells:
2215            if c == 2:
2216                for i in range(len(cells)):
2217                    cells[i][-2] = False
2218                    UnitCellsTable.SetValue(i,c,False)
2219                UnitCellsTable.SetValue(r,c,True)
2220                gridDisplay.ForceRefresh()
2221                cells[r][-2] = True
2222                ibrav = cells[r][2]
2223                A = G2lat.cell2A(cells[r][3:9])
2224                G2frame.HKL = G2lat.GenHBravais(dmin,ibrav,A)
2225                for hkl in G2frame.HKL:
2226                    hkl.append(G2lat.Dsp2pos(Inst,hkl[3])+controls[1])
2227                if 'PKS' in G2frame.PatternTree.GetItemText(G2frame.PatternId):
2228                    G2plt.PlotPowderLines(G2frame)
2229                else:
2230                    G2plt.PlotPatterns(G2frame)
2231            elif c == 11:
2232                if UnitCellsTable.GetValue(r,c):
2233                    UnitCellsTable.SetValue(r,c,False)
2234                    cells[r][c] = False
2235                else:
2236                    cells[r][c] = True
2237                    UnitCellsTable.SetValue(r,c,True)
2238                gridDisplay.ForceRefresh()
2239            G2frame.PatternTree.SetItemPyData(UnitCellsId,data)               
2240       
2241    def MakeNewPhase(event):
2242        if not G2gd.GetPatternTreeItemId(G2frame,G2frame.root,'Phases'):
2243            sub = G2frame.PatternTree.AppendItem(parent=G2frame.root,text='Phases')
2244        else:
2245            sub = G2gd.GetPatternTreeItemId(G2frame,G2frame.root,'Phases')
2246        PhaseName = ''
2247        dlg = wx.TextEntryDialog(None,'Enter a name for this phase','Phase Name Entry','New phase',
2248            style=wx.OK)
2249        try:
2250            if dlg.ShowModal() == wx.ID_OK:
2251                PhaseName = dlg.GetValue()
2252                cells = G2frame.PatternTree.GetItemPyData(UnitCellsId)[2]
2253                for Cell in cells:
2254                    if Cell[-2]:
2255                        break
2256                cell = Cell[2:10]       
2257                sub = G2frame.PatternTree.AppendItem(parent=sub,text=PhaseName)
2258                E,SGData = G2spc.SpcGroup(controls[13])
2259                G2frame.PatternTree.SetItemPyData(sub, \
2260                    G2IO.SetNewPhase(Name=PhaseName,SGData=SGData,cell=cell[1:]))
2261                Status.SetStatusText('Change space group from '+str(controls[13])+' if needed')
2262        finally:
2263            dlg.Destroy()
2264           
2265    if G2frame.dataDisplay:
2266        G2frame.dataFrame.Clear()
2267    G2gd.SetDataMenuBar(G2frame,G2frame.dataFrame.IndexMenu)
2268    if not G2frame.dataFrame.GetStatusBar():
2269        Status = G2frame.dataFrame.CreateStatusBar()
2270    G2frame.Bind(wx.EVT_MENU, IndexPeaks, id=G2gd.wxID_INDEXPEAKS)
2271    G2frame.Bind(wx.EVT_MENU, CopyUnitCell, id=G2gd.wxID_COPYCELL)
2272    G2frame.Bind(wx.EVT_MENU, RefineCell, id=G2gd.wxID_REFINECELL)
2273    G2frame.Bind(wx.EVT_MENU, MakeNewPhase, id=G2gd.wxID_MAKENEWPHASE)
2274   
2275    controls,bravais,cells,dmin = data
2276    if len(controls) < 13:              #add cell volume if missing
2277        controls.append(G2lat.calc_V(G2lat.cell2A(controls[6:12])))
2278    if len(controls) < 14:              #add space gropu used in indexing
2279        controls.append(spaceGroups[bravaisSymb.index(controls[5])])
2280    G2frame.PatternTree.SetItemPyData(UnitCellsId,data)            #update with volume
2281    bravaisNames = ['Cubic-F','Cubic-I','Cubic-P','Trigonal-R','Trigonal/Hexagonal-P',
2282        'Tetragonal-I','Tetragonal-P','Orthorhombic-F','Orthorhombic-I','Orthorhombic-C',
2283        'Orthorhombic-P','Monoclinic-C','Monoclinic-P','Triclinic']
2284    cellGUIlist = [[[0,1,2],4,zip([" Unit cell: a = "," Vol = "],["%.5f","%.3f"],[True,False],[0,0])],
2285    [[3,4,5,6],6,zip([" Unit cell: a = "," c = "," Vol = "],["%.5f","%.5f","%.3f"],[True,True,False],[0,2,0])],
2286    [[7,8,9,10],8,zip([" Unit cell: a = "," b = "," c = "," Vol = "],["%.5f","%.5f","%.5f","%.3f"],
2287        [True,True,True,False],[0,1,2,0])],
2288    [[11,12],10,zip([" Unit cell: a = "," b = "," c = "," beta = "," Vol = "],
2289        ["%.5f","%.5f","%.5f","%.3f","%.3f"],[True,True,True,True,False],[0,1,2,4,0])],
2290    [[13,],8,zip([" Unit cell: a = "," b = "," c = "," Vol = "," alpha = "," beta = "," gamma = "],
2291        ["%.5f","%.5f","%.5f","%.3f","%.3f","%.3f","%.3f"],
2292        [True,True,True,False,True,True,True],[0,1,2,0,3,4,5])]]
2293   
2294    G2frame.dataFrame.SetLabel('Unit Cells List')
2295    G2frame.sp = wx.SplitterWindow(G2frame.dataFrame)
2296    G2frame.dataDisplay = wx.Panel(G2frame.sp, style=wx.SUNKEN_BORDER)
2297    G2frame.dataFrame.IndexPeaks.Enable(False)
2298    peaks = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,G2frame.PatternId, 'Index Peak List'))
2299    if peaks:
2300        G2frame.dataFrame.IndexPeaks.Enable(True)
2301    G2frame.dataFrame.RefineCell.Enable(False)
2302    if controls[12] > 1.0:                               #if a "real" volume (i.e. not default)
2303        G2frame.dataFrame.RefineCell.Enable(True)   
2304    G2frame.dataFrame.CopyCell.Enable(False)
2305    G2frame.dataFrame.MakeNewPhase.Enable(False)       
2306    if cells:
2307        G2frame.bottom = wx.Panel(G2frame.sp, style=wx.SUNKEN_BORDER)
2308        G2frame.sp.SplitHorizontally(G2frame.dataDisplay,G2frame.bottom,0)
2309        G2frame.dataFrame.CopyCell.Enable(True)
2310        G2frame.dataFrame.MakeNewPhase.Enable(True)       
2311    mainSizer = wx.BoxSizer(wx.VERTICAL)
2312    mainSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' Indexing controls: '),0,WACV)
2313    mainSizer.Add((5,5),0)
2314    littleSizer = wx.FlexGridSizer(0,5,5,5)
2315    littleSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' Max Nc/Nobs '),0,WACV)
2316    NcNo = wx.SpinCtrl(G2frame.dataDisplay)
2317    NcNo.SetRange(1,6)
2318    NcNo.SetValue(controls[2])
2319    NcNo.Bind(wx.EVT_SPINCTRL,OnNcNo)
2320    littleSizer.Add(NcNo,0,WACV)
2321    littleSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' Start Volume '),0,WACV)
2322    startVol = wx.TextCtrl(G2frame.dataDisplay,value=str('%d'%(controls[3])),style=wx.TE_PROCESS_ENTER)
2323    startVol.Bind(wx.EVT_TEXT_ENTER,OnStartVol)
2324    startVol.Bind(wx.EVT_KILL_FOCUS,OnStartVol)
2325    littleSizer.Add(startVol,0,WACV)
2326    mainSizer.Add(littleSizer,0)
2327    mainSizer.Add((5,5),0)
2328    mainSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Select Bravais Lattices for indexing: '),
2329        0,WACV)
2330    mainSizer.Add((5,5),0)
2331    littleSizer = wx.FlexGridSizer(0,7,5,5)
2332    bravList = []
2333    bravs = zip(bravais,bravaisNames)
2334    for brav,bravName in bravs:
2335        bravCk = wx.CheckBox(G2frame.dataDisplay,label=bravName)
2336        bravList.append(bravCk.GetId())
2337        bravCk.SetValue(brav)
2338        bravCk.Bind(wx.EVT_CHECKBOX,OnBravais)
2339        littleSizer.Add(bravCk,0,WACV)
2340    mainSizer.Add(littleSizer,0)
2341    mainSizer.Add((5,5),0)
2342   
2343    mainSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' Cell Refinement: '),0,WACV)
2344    mainSizer.Add((5,5),0)
2345    littleSizer = wx.BoxSizer(wx.HORIZONTAL)
2346    littleSizer.Add(wx.StaticText(G2frame.dataDisplay,label=" Bravais lattice "),0,WACV)
2347    bravSel = wx.Choice(G2frame.dataDisplay,choices=bravaisSymb)
2348    bravSel.SetSelection(bravaisSymb.index(controls[5]))
2349    bravSel.Bind(wx.EVT_CHOICE,OnBravSel)
2350    littleSizer.Add(bravSel,0,WACV)
2351    littleSizer.Add(wx.StaticText(G2frame.dataDisplay,label=" Space group "),0,WACV)
2352    spcSel = wx.Choice(G2frame.dataDisplay,choices=SPGlist[controls[5]])
2353    spcSel.SetSelection(SPGlist[controls[5]].index(controls[13]))
2354    spcSel.Bind(wx.EVT_CHOICE,OnSpcSel)
2355    littleSizer.Add(spcSel,0,WACV)
2356    littleSizer.Add(wx.StaticText(G2frame.dataDisplay,label=" Zero offset"),0,WACV)
2357    zero = wx.TextCtrl(G2frame.dataDisplay,value="%.4f"%(controls[1]),style=wx.TE_PROCESS_ENTER)
2358    zero.Bind(wx.EVT_TEXT_ENTER,OnZero)
2359    zero.Bind(wx.EVT_KILL_FOCUS,OnZero)
2360    littleSizer.Add(zero,0,WACV)
2361    zeroVar = wx.CheckBox(G2frame.dataDisplay,label="Refine?")
2362    zeroVar.SetValue(controls[0])
2363    zeroVar.Bind(wx.EVT_CHECKBOX,OnZeroVar)
2364    littleSizer.Add(zeroVar,0,WACV)
2365    hklShow = wx.Button(G2frame.dataDisplay,label="Show hkl positions")
2366    hklShow.Bind(wx.EVT_BUTTON,OnHklShow)
2367    littleSizer.Add(hklShow,0,WACV)
2368    mainSizer.Add(littleSizer,0)
2369   
2370    mainSizer.Add((5,5),0)
2371    ibrav = SetLattice(controls)
2372    for cellGUI in cellGUIlist:
2373        if ibrav in cellGUI[0]:
2374            useGUI = cellGUI
2375    cellList = []
2376    littleSizer = wx.FlexGridSizer(0,useGUI[1],5,5)
2377    for txt,fmt,ifEdit,Id in useGUI[2]:
2378        littleSizer.Add(wx.StaticText(G2frame.dataDisplay,label=txt),0,WACV)
2379        if ifEdit:          #a,b,c,etc.
2380            cellVal = wx.TextCtrl(G2frame.dataDisplay,value=(fmt%(controls[6+Id])),style=wx.TE_PROCESS_ENTER)
2381            cellVal.Bind(wx.EVT_TEXT_ENTER,OnCellChange)       
2382            cellVal.Bind(wx.EVT_KILL_FOCUS,OnCellChange)
2383            littleSizer.Add(cellVal,0,WACV)
2384            cellList.append(cellVal.GetId())
2385        else:               #volume
2386            volVal = wx.TextCtrl(G2frame.dataDisplay,value=(fmt%(controls[12])),style=wx.TE_READONLY)
2387            volVal.SetBackgroundColour(VERY_LIGHT_GREY)
2388            littleSizer.Add(volVal,0,WACV)
2389    mainSizer.Add(littleSizer,0)
2390       
2391    mainSizer.Layout()   
2392    G2frame.dataDisplay.SetSizer(mainSizer)
2393    topSize = mainSizer.Fit(G2frame.dataFrame)
2394    G2frame.dataDisplay.SetSize(topSize)
2395    if cells:
2396        if ibrav == 13:
2397            topSize[1] += 230
2398        else:
2399            topSize[1] += 200
2400    G2frame.dataFrame.setSizePosLeft(topSize)   
2401   
2402    if cells:
2403        bottomSize = topSize        #screwy but bottom doesn't have a size in linux!
2404        bottomSize[0] -= 20         #to reveal slider
2405        if ibrav == 13:
2406            bottomSize[1] -= 240
2407        else:
2408            bottomSize[1] -= 210
2409        wx.StaticText(parent=G2frame.bottom,label=' Indexing Result ')
2410        rowLabels = []
2411        colLabels = ['M20','X20','use','Bravais','a','b','c','alpha','beta','gamma','Volume','Keep']
2412        Types = [wg.GRID_VALUE_FLOAT+':10,2',wg.GRID_VALUE_NUMBER,wg.GRID_VALUE_BOOL,wg.GRID_VALUE_STRING,]+ \
2413            3*[wg.GRID_VALUE_FLOAT+':10,5',]+3*[wg.GRID_VALUE_FLOAT+':10,3',]+ \
2414            [wg.GRID_VALUE_FLOAT+':10,2',wg.GRID_VALUE_BOOL]
2415        numRows = len(cells)
2416        table = []
2417        for cell in cells:
2418            rowLabels.append('')
2419            row = cell[0:2]+[cell[-2]]+[bravaisSymb[cell[2]]]+cell[3:10]+[cell[11],]
2420            if cell[-2]:
2421                A = G2lat.cell2A(cell[3:9])
2422                G2frame.HKL = G2lat.GenHBravais(dmin,cell[2],A)
2423                for hkl in G2frame.HKL:
2424                    hkl.append(G2lat.Dsp2pos(Inst,hkl[3])+controls[1])
2425            table.append(row)
2426        UnitCellsTable = G2gd.Table(table,rowLabels=rowLabels,colLabels=colLabels,types=Types)
2427        gridDisplay = G2gd.GSGrid(G2frame.bottom)
2428        gridDisplay.SetPosition(wx.Point(0,20))               
2429        gridDisplay.SetTable(UnitCellsTable, True)
2430        G2frame.dataFrame.CopyCell.Enable(True)
2431        gridDisplay.Bind(wg.EVT_GRID_CELL_LEFT_CLICK,RefreshUnitCellsGrid)
2432        gridDisplay.Bind(wg.EVT_GRID_LABEL_LEFT_DCLICK,OnSortCells)
2433        gridDisplay.SetMargins(0,0)
2434        gridDisplay.SetRowLabelSize(0)
2435        gridDisplay.AutoSizeColumns(False)
2436        for r in range(gridDisplay.GetNumberRows()):
2437            for c in range(gridDisplay.GetNumberCols()):
2438                if c == 2:
2439                    gridDisplay.SetReadOnly(r,c,isReadOnly=False)
2440                else:
2441                    gridDisplay.SetReadOnly(r,c,isReadOnly=True)
2442        gridDisplay.SetSize(bottomSize)
2443
2444################################################################################
2445#####  Reflection list
2446################################################################################           
2447       
2448def UpdateReflectionGrid(G2frame,data,HKLF=False,Name=''):
2449    '''respond to selection of PWDR Reflections data tree item.
2450    '''
2451    if not data:
2452        print 'No phases, no reflections'
2453        return
2454    if HKLF:
2455        G2frame.RefList = 1
2456        phaseName = Name
2457    else:
2458        phaseName = G2frame.RefList
2459        phases = data.keys()
2460   
2461        def OnSelectPhase(event):
2462            dlg = wx.SingleChoiceDialog(G2frame,'Select','Phase',phases)
2463            try:
2464                if dlg.ShowModal() == wx.ID_OK:
2465                    sel = dlg.GetSelection()
2466                    G2frame.RefList = phases[sel]
2467                    UpdateReflectionGrid(G2frame,data)
2468            finally:
2469                dlg.Destroy()
2470            G2plt.PlotPatterns(G2frame)
2471           
2472        def OnPlotHKL(event):
2473            FoMax = np.max(refList.T[8])
2474            Hmin = np.array([int(np.min(refList.T[0])),int(np.min(refList.T[1])),int(np.min(refList.T[2]))])
2475            Hmax = np.array([int(np.max(refList.T[0])),int(np.max(refList.T[1])),int(np.max(refList.T[2]))])
2476            controls = {'Type' : 'Fo','ifFc' : True,'HKLmax' : Hmax,'HKLmin' : Hmin,
2477                'FoMax' : FoMax,'Zone' : '001','Layer' : 0,'Scale' : 1.0,}
2478            G2plt.PlotSngl(G2frame,newPlot=True,Data=controls,hklRef=refList,Title=phaseName)
2479           
2480        def OnPlot3DHKL(event):
2481            FoMax = np.max(refList.T[8])
2482            Hmin = np.array([int(np.min(refList.T[0])),int(np.min(refList.T[1])),int(np.min(refList.T[2]))])
2483            Hmax = np.array([int(np.max(refList.T[0])),int(np.max(refList.T[1])),int(np.max(refList.T[2]))])
2484            Vpoint = [int(np.mean(refList.T[0])),int(np.mean(refList.T[1])),int(np.mean(refList.T[2]))]
2485            controls = {'Type':'Fosq','Iscale':False,'HKLmax':Hmax,'HKLmin':Hmin,
2486                'FoMax' : FoMax,'Scale' : 1.0,'Drawing':{'viewPoint':[Vpoint,[]],'default':Vpoint[:],
2487                'backColor':[0,0,0],'depthFog':False,'Zclip':10.0,'cameraPos':10.,'Zstep':0.05,
2488                'Scale':1.0,'oldxy':[],'viewDir':[1,0,0]}}
2489            G2plt.Plot3DSngl(G2frame,newPlot=True,Data=controls,hklRef=refList,Title=phaseName)
2490       
2491    if G2frame.dataDisplay:
2492        G2frame.dataFrame.Clear()
2493    Inst = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,G2frame.PatternId, 'Instrument Parameters'))[0]
2494    rowLabels = []
2495    if HKLF:
2496        G2gd.SetDataMenuBar(G2frame)
2497        refs = data[1]['RefList']
2498    else:       
2499        G2gd.SetDataMenuBar(G2frame,G2frame.dataFrame.ReflMenu)
2500        if not G2frame.dataFrame.GetStatusBar():
2501            Status = G2frame.dataFrame.CreateStatusBar()   
2502        G2frame.Bind(wx.EVT_MENU, OnSelectPhase, id=G2gd.wxID_SELECTPHASE)
2503        G2frame.Bind(wx.EVT_MENU, OnPlotHKL, id=G2gd.wxID_PWDHKLPLOT)
2504        G2frame.Bind(wx.EVT_MENU, OnPlot3DHKL, id=G2gd.wxID_PWD3DHKLPLOT)
2505        G2frame.dataFrame.SelectPhase.Enable(False)
2506        if len(data) > 1:
2507            G2frame.dataFrame.SelectPhase.Enable(True)
2508        try:            #patch for old reflection lists
2509            refList = np.array(data[G2frame.RefList]['RefList'])
2510            I100 = refList.T[8]*refList.T[11]
2511        except TypeError:
2512            refList = np.array([refl[:11] for refl in data[G2frame.RefList]])
2513            I100 = refList.T[8]*np.array([refl[11] for refl in data[G2frame.RefList]])
2514        Imax = np.max(I100)
2515        if Imax:
2516            I100 *= 100.0/Imax
2517        if 'C' in Inst['Type'][0]:
2518            refs = np.vstack((refList.T[:11],I100)).T
2519        elif 'T' in Inst['Type'][0]:
2520            refs = np.vstack((refList.T[:15],I100)).T
2521           
2522    for i in range(len(refs)): rowLabels.append(str(i))
2523    Types = 4*[wg.GRID_VALUE_LONG,]+4*[wg.GRID_VALUE_FLOAT+':10,4',]+ \
2524        2*[wg.GRID_VALUE_FLOAT+':10,2',]+[wg.GRID_VALUE_FLOAT+':10,3',]+ \
2525        [wg.GRID_VALUE_FLOAT+':10,3',]
2526    if HKLF:
2527        colLabels = ['H','K','L','mul','d','Fosq','sig','Fcsq','FoTsq','FcTsq','phase','Ext',]
2528    else:
2529        if 'C' in Inst['Type'][0]:
2530            colLabels = ['H','K','L','mul','d','pos','sig','gam','Fosq','Fcsq','phase','Icorr','I100',]
2531            Types += [wg.GRID_VALUE_FLOAT+':10,3',]
2532        elif 'T' in Inst['Type'][0]:
2533            colLabels = ['H','K','L','mul','d','pos','sig','gam','Fosq','Fcsq','phase','Icorr','alp','bet','wave','I100',]
2534            Types += 4*[wg.GRID_VALUE_FLOAT+':10,3',]
2535           
2536    G2frame.PeakTable = G2gd.Table(refs,rowLabels=rowLabels,colLabels=colLabels,types=Types)
2537    G2frame.dataFrame.SetLabel('Reflection List for '+phaseName)
2538    G2frame.dataDisplay = G2gd.GSGrid(parent=G2frame.dataFrame)
2539    G2frame.dataDisplay.SetTable(G2frame.PeakTable, True)
2540    G2frame.dataDisplay.EnableEditing(False)
2541    G2frame.dataDisplay.SetMargins(0,0)
2542    G2frame.dataDisplay.AutoSizeColumns(False)
2543    G2frame.dataDisplay.Fit()
2544    size = G2frame.dataDisplay.GetSize()
2545    G2frame.dataFrame.setSizePosLeft([size[0]+32,350])
2546   
2547################################################################################
2548#####  SASD Substances
2549################################################################################
2550           
2551def UpdateSubstanceGrid(G2frame,data):
2552    '''respond to selection of SASD Substance data tree item.
2553    '''
2554    import Substances as substFile
2555   
2556    def OnLoadSubstance(event):
2557        names = substFile.Substances.keys()
2558        names.sort()
2559        dlg = wx.SingleChoiceDialog(G2frame, 'Which substance?', 'Select substance', names, wx.CHOICEDLG_STYLE)
2560        try:
2561            if dlg.ShowModal() == wx.ID_OK:
2562                name = names[dlg.GetSelection()]
2563            else:
2564                return
2565        finally:
2566            dlg.Destroy()
2567        data['Substances'][name] = {'Elements':{},'Volume':1.0,'Density':1.0,
2568            'Scatt density':0.0,'XAnom density':0.0,'XAbsorption':0.0}
2569        subst = substFile.Substances[name]
2570        ElList = subst['Elements'].keys()
2571        for El in ElList:
2572            Info = G2elem.GetAtomInfo(El.strip().capitalize())
2573            Info.update(subst['Elements'][El])
2574            data['Substances'][name]['Elements'][El] = Info
2575            if 'Volume' in subst:
2576                data['Substances'][name]['Volume'] = subst['Volume']
2577                data['Substances'][name]['Density'] = \
2578                    G2mth.Vol2Den(data['Substances'][name]['Elements'],data['Substances'][name]['Volume'])
2579            elif 'Density' in subst:
2580                data['Substances'][name]['Density'] = subst['Density']
2581                data['Substances'][name]['Volume'] = \
2582                    G2mth.Den2Vol(data['Substances'][name]['Elements'],data['Substances'][name]['Density'])
2583            else:
2584                data['Substances'][name]['Volume'] = G2mth.El2EstVol(data['Substances'][name]['Elements'])
2585                data['Substances'][name]['Density'] = \
2586                    G2mth.Vol2Den(data['Substances'][name]['Elements'],data['Substances'][name]['Volume'])
2587            data['Substances'][name]['Scatt density'] = \
2588                G2mth.XScattDen(data['Substances'][name]['Elements'],data['Substances'][name]['Volume'])[0]
2589            contrst,absorb = G2mth.XScattDen(data['Substances'][name]['Elements'],data['Substances'][name]['Volume'],wave)         
2590            data['Substances'][name]['XAnom density'] = contrst
2591            data['Substances'][name]['XAbsorption'] = absorb
2592                         
2593        UpdateSubstanceGrid(G2frame,data)
2594       
2595    def OnCopySubstance(event):
2596        hst = G2frame.PatternTree.GetItemText(G2frame.PatternId)
2597        histList = GetHistsLikeSelected(G2frame)
2598        if not histList:
2599            G2frame.ErrorDialog('No match','No histograms match '+hst,G2frame.dataFrame)
2600            return
2601        copyList = []
2602        dlg = G2gd.G2MultiChoiceDialog(
2603            G2frame.dataFrame, 
2604            'Copy substances from\n'+hst[5:]+' to...',
2605            'Copy substances', histList)
2606        try:
2607            if dlg.ShowModal() == wx.ID_OK:
2608                for i in dlg.GetSelections(): 
2609                    copyList.append(histList[i])
2610        finally:
2611            dlg.Destroy()       
2612        for item in copyList:
2613            Id = G2gd.GetPatternTreeItemId(G2frame,G2frame.root,item)
2614            G2frame.PatternTree.SetItemPyData(G2gd.GetPatternTreeItemId(G2frame,Id,'Substances'),
2615                copy.copy(data))
2616   
2617    def OnAddSubstance(event):
2618        dlg = wx.TextEntryDialog(None,'Enter a name for this substance','Substance Name Entry','New substance',
2619            style=wx.OK)
2620        if dlg.ShowModal() == wx.ID_OK:
2621            Name = dlg.GetValue()
2622            data['Substances'][Name] = {'Elements':{},'Volume':1.0,'Density':1.0,
2623                'Scatt density':0.0,'XAnom density':0.,'XAbsorption':0.}
2624        dlg.Destroy()
2625        AddElement(Name)
2626        UpdateSubstanceGrid(G2frame,data)
2627       
2628    def OnDeleteSubstance(event):
2629        TextList = []
2630        for name in data['Substances']:
2631            if name != 'vacuum':
2632                TextList += [name,]
2633        if not TextList:
2634            return
2635        dlg = wx.SingleChoiceDialog(G2frame, 'Which substance?', 'Select substance to delete', TextList, wx.CHOICEDLG_STYLE)
2636        try:
2637            if dlg.ShowModal() == wx.ID_OK:
2638                name = TextList[dlg.GetSelection()]
2639            else:
2640                return
2641        finally:
2642            dlg.Destroy()
2643        del(data['Substances'][name])
2644        UpdateSubstanceGrid(G2frame,data)       
2645               
2646    def OnAddElement(event):       
2647        TextList = []
2648        for name in data['Substances']:
2649            if name != 'vacuum':
2650                TextList += [name,]
2651        if not TextList:
2652            return
2653        dlg = wx.SingleChoiceDialog(G2frame, 'Which substance?', 'Select substance', TextList, wx.CHOICEDLG_STYLE)
2654        try:
2655            if dlg.ShowModal() == wx.ID_OK:
2656                name = TextList[dlg.GetSelection()]
2657            else:
2658                return
2659        finally:
2660            dlg.Destroy()
2661        AddElement(name)
2662        UpdateSubstanceGrid(G2frame,data)
2663       
2664    def AddElement(name):
2665        ElList = data['Substances'][name]['Elements'].keys()
2666        dlg = G2elemGUI.PickElements(G2frame,ElList)
2667        if dlg.ShowModal() == wx.ID_OK:
2668            for El in dlg.Elem:
2669                El = El.strip().capitalize()
2670                Info = G2elem.GetAtomInfo(El)
2671                Info.update({'Num':1})
2672                data['Substances'][name]['Elements'][El] = Info
2673                data['Substances'][name]['Volume'] = G2mth.El2EstVol(data['Substances'][name]['Elements'])
2674                data['Substances'][name]['Density'] = \
2675                    G2mth.Vol2Den(data['Substances'][name]['Elements'],data['Substances'][name]['Volume'])
2676                data['Substances'][name]['Scatt density'] = \
2677                    G2mth.XScattDen(data['Substances'][name]['Elements'],data['Substances'][name]['Volume'])[0]
2678                contrst,absorb = G2mth.XScattDen(data['Substances'][name]['Elements'],data['Substances'][name]['Volume'],wave)         
2679                data['Substances'][name]['XAnom density'] = contrst
2680                data['Substances'][name]['XAbsorption'] = absorb
2681        dlg.Destroy()
2682       
2683    def OnDeleteElement(event):
2684        TextList = []
2685        for name in data['Substances']:
2686            if name != 'vacuum':
2687                TextList += [name,]
2688        if not TextList:
2689            return
2690        dlg = wx.SingleChoiceDialog(G2frame, 'Which substance?', 'Select substance', TextList, wx.CHOICEDLG_STYLE)
2691        try:
2692            if dlg.ShowModal() == wx.ID_OK:
2693                name = TextList[dlg.GetSelection()]
2694            else:
2695                return
2696        finally:
2697            dlg.Destroy()
2698        ElList = data['Substances'][name]['Elements'].keys()
2699        if len(ElList):
2700            DE = G2elemGUI.DeleteElement(G2frame,ElList)
2701            if DE.ShowModal() == wx.ID_OK:
2702                El = DE.GetDeleteElement().strip().upper()
2703                del(data['Substances'][name]['Elements'][El])
2704                data['Substances'][name]['Volume'] = G2mth.El2EstVol(data['Substances'][name]['Elements'])
2705                data['Substances'][name]['Density'] = \
2706                    G2mth.Vol2Den(data['Substances'][name]['Elements'],data['Substances'][name]['Volume'])
2707                data['Substances'][name]['Scatt density'] = \
2708                    G2mth.XScattDen(data['Substances'][name]['Elements'],data['Substances'][name]['Volume'])[0]
2709                contrst,absorb = G2mth.XScattDen(data['Substances'][name]['Elements'],data['Substances'][name]['Volume'],wave)         
2710                data['Substances'][name]['XAnom density'] = contrst
2711                data['Substances'][name]['XAbsorption'] = absorb
2712        UpdateSubstanceGrid(G2frame,data)
2713               
2714    def SubstSizer():
2715       
2716        def OnValueChange(event):
2717            Obj = event.GetEventObject()
2718            if len(Indx[Obj.GetId()]) == 3:
2719                name,El,keyId = Indx[Obj.GetId()]
2720                try:
2721                    value = max(0,float(Obj.GetValue()))
2722                except ValueError:
2723                    value = 0
2724                    Obj.SetValue('%.2f'%(value))
2725                data['Substances'][name]['Elements'][El][keyId] = value
2726                data['Substances'][name]['Volume'] = G2mth.El2EstVol(data['Substances'][name]['Elements'])
2727                data['Substances'][name]['Density'] = \
2728                    G2mth.Vol2Den(data['Substances'][name]['Elements'],data['Substances'][name]['Volume'])
2729            else:
2730                name,keyId = Indx[Obj.GetId()]
2731                try:
2732                    value = max(0,float(Obj.GetValue()))
2733                except ValueError:
2734                    value = 1.0
2735                data['Substances'][name][keyId] = value
2736                if keyId in 'Volume':
2737                    data['Substances'][name]['Density'] = \
2738                        G2mth.Vol2Den(data['Substances'][name]['Elements'],value)
2739                elif keyId in 'Density':
2740                    data['Substances'][name]['Volume'] = \
2741                        G2mth.Den2Vol(data['Substances'][name]['Elements'],value)
2742            data['Substances'][name]['Scatt density'] = \
2743                G2mth.XScattDen(data['Substances'][name]['Elements'],data['Substances'][name]['Volume'])[0]
2744            contrst,absorb = G2mth.XScattDen(data['Substances'][name]['Elements'],data['Substances'][name]['Volume'],wave)         
2745            data['Substances'][name]['XAnom density'] = contrst
2746            data['Substances'][name]['XAbsorption'] = absorb
2747            wx.CallAfter(UpdateSubstanceGrid,G2frame,data)
2748       
2749        Indx = {}
2750        substSizer = wx.BoxSizer(wx.VERTICAL)
2751        substSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' Substance list: wavelength: %.5fA'%(wave)),
2752            0,WACV)
2753        for name in data['Substances']:
2754            G2gd.HorizontalLine(substSizer,G2frame.dataDisplay)   
2755            substSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' Data for '+name+':'),
2756                0,WACV)
2757            if name == 'vacuum':
2758                substSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label='        Not applicable'),
2759                    0,WACV)
2760            else:   
2761                elSizer = wx.FlexGridSizer(0,6,5,5)
2762                Substance = data['Substances'][name]
2763                Elems = Substance['Elements']
2764                for El in Elems:    #do elements as pull downs for isotopes for neutrons
2765                    elSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' '+El+': '),
2766                        0,WACV)
2767                    num = wx.TextCtrl(G2frame.dataDisplay,value='%.2f'%(Elems[El]['Num']),style=wx.TE_PROCESS_ENTER)
2768                    Indx[num.GetId()] = [name,El,'Num']
2769                    num.Bind(wx.EVT_TEXT_ENTER,OnValueChange)       
2770                    num.Bind(wx.EVT_KILL_FOCUS,OnValueChange)
2771                    elSizer.Add(num,0,WACV)
2772                substSizer.Add(elSizer,0)
2773                vdsSizer = wx.FlexGridSizer(0,4,5,5)
2774                vdsSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' Volume: '),
2775                    0,WACV)
2776                vol = wx.TextCtrl(G2frame.dataDisplay,value='%.3f'%(Substance['Volume']),style=wx.TE_PROCESS_ENTER)
2777                Indx[vol.GetId()] = [name,'Volume']
2778                vol.Bind(wx.EVT_TEXT_ENTER,OnValueChange)       
2779                vol.Bind(wx.EVT_KILL_FOCUS,OnValueChange)
2780                vdsSizer.Add(vol,0,WACV)               
2781                vdsSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' Density: '),
2782                    0,WACV)
2783                den = wx.TextCtrl(G2frame.dataDisplay,value='%.3f'%(Substance['Density']),style=wx.TE_PROCESS_ENTER)
2784                Indx[den.GetId()] = [name,'Density']
2785                den.Bind(wx.EVT_TEXT_ENTER,OnValueChange)       
2786                den.Bind(wx.EVT_KILL_FOCUS,OnValueChange)
2787                vdsSizer.Add(den,0,WACV)
2788                substSizer.Add(vdsSizer,0)
2789                substSizer.Add(wx.StaticText(G2frame.dataDisplay,
2790                    label=' Scattering density  : %.2f *10%scm%s'%(Substance['Scatt density'],Pwr10,Pwrm2)),
2791                    0,WACV)               
2792                substSizer.Add(wx.StaticText(G2frame.dataDisplay,       #allow neutrons here into NAnom density & NAbsorption
2793                    label=' Anomalous density : %.2f *10%scm%s'%(Substance['XAnom density'],Pwr10,Pwrm2)),
2794                    0,WACV)               
2795                substSizer.Add(wx.StaticText(G2frame.dataDisplay,
2796                    label=' X-ray absorption   : %.2f cm%s'%(Substance['XAbsorption'],Pwrm1)),
2797                    0,WACV)               
2798        return substSizer
2799           
2800    Inst = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,G2frame.PatternId, 'Instrument Parameters'))[0]
2801    wave = G2mth.getWave(Inst)
2802    if G2frame.dataDisplay:
2803        G2frame.dataFrame.DestroyChildren()
2804    G2gd.SetDataMenuBar(G2frame,G2frame.dataFrame.SubstanceMenu)
2805    if not G2frame.dataFrame.GetStatusBar():
2806        Status = G2frame.dataFrame.CreateStatusBar()
2807    G2frame.dataDisplay = wxscroll.ScrolledPanel(G2frame.dataFrame)
2808    G2frame.dataFrame.SetLabel('Substances')
2809    G2frame.dataFrame.Bind(wx.EVT_MENU, OnLoadSubstance, id=G2gd.wxID_LOADSUBSTANCE)   
2810    G2frame.dataFrame.Bind(wx.EVT_MENU, OnAddSubstance, id=G2gd.wxID_ADDSUBSTANCE)
2811    G2frame.dataFrame.Bind(wx.EVT_MENU, OnCopySubstance, id=G2gd.wxID_COPYSUBSTANCE)
2812    G2frame.dataFrame.Bind(wx.EVT_MENU, OnDeleteSubstance, id=G2gd.wxID_DELETESUBSTANCE)   
2813    G2frame.dataFrame.Bind(wx.EVT_MENU, OnAddElement, id=G2gd.wxID_ELEMENTADD)
2814    G2frame.dataFrame.Bind(wx.EVT_MENU, OnDeleteElement, id=G2gd.wxID_ELEMENTDELETE)
2815    mainSizer = wx.BoxSizer(wx.VERTICAL)
2816    mainSizer.Add(SubstSizer(),0)
2817
2818    mainSizer.Layout()   
2819    G2frame.dataDisplay.SetSizer(mainSizer)
2820    G2frame.dataDisplay.SetAutoLayout(1)
2821    G2frame.dataDisplay.SetupScrolling()
2822    Size = mainSizer.Fit(G2frame.dataFrame)
2823    Size[0] += 25
2824    G2frame.dataDisplay.SetSize(Size)
2825    G2frame.dataFrame.setSizePosLeft(Size)   
2826       
2827################################################################################
2828#####  SASD Models
2829################################################################################           
2830       
2831def UpdateModelsGrid(G2frame,data):
2832    '''respond to selection of SASD Models data tree item.
2833    '''
2834    #patches
2835    if 'Current' not in data:
2836        data['Current'] = 'Size dist.'
2837    if 'logBins' not in data['Size']:
2838        data['Size']['logBins'] = True
2839    if 'MinMaxDiam' in data['Size']:
2840        data['Size']['MinDiam'] = 50.
2841        data['Size']['MaxDiam'] = 10000.
2842        del data['Size']['MinMaxDiam']
2843    if isinstance(data['Size']['MaxEnt']['Sky'],float):
2844        data['Size']['MaxEnt']['Sky'] = -3
2845    if 'Power' not in data['Size']['IPG']:
2846        data['Size']['IPG']['Power'] = -1
2847    if 'Matrix' not in data['Particle']:
2848        data['Particle']['Matrix'] = {'Name':'vacuum','VolFrac':[0.0,False]}
2849    if 'BackFile' not in data:
2850        data['BackFile'] = ''
2851    #end patches
2852   
2853    def RefreshPlots(newPlot=False):
2854        PlotText = G2frame.G2plotNB.nb.GetPageText(G2frame.G2plotNB.nb.GetSelection())
2855        if 'Powder' in PlotText:
2856            G2plt.PlotPatterns(G2frame,plotType='SASD',newPlot=newPlot)
2857        elif 'Size' in PlotText:
2858            G2plt.PlotSASDSizeDist(G2frame)
2859               
2860    def OnAddModel(event):
2861        if data['Current'] == 'Particle fit':
2862            material = 'vacuum'
2863            if len(data['Particle']['Levels']):
2864                material = data['Particle']['Levels'][-1]['Controls']['Material']
2865            data['Particle']['Levels'].append({
2866                'Controls':{'FormFact':'Sphere','DistType':'LogNormal','Material':material,
2867                    'FFargs':{},'SFargs':{},'NumPoints':50,'Cutoff':0.01,'Contrast':0.0,
2868                    'SlitSmear':[0.0,False],'StrFact':'Dilute'},    #last 2 not used - future?
2869                'LogNormal':{'Volume':[0.05,False],'Mean':[1000.,False],'StdDev':[0.5,False],'MinSize':[10.,False],},
2870                'Gaussian':{'Volume':[0.05,False],'Mean':[1000.,False],'StdDev':[300.,False],},
2871                'LSW':{'Volume':[0.05,False],'Mean':[1000.0,False],},
2872                'Schulz-Zimm':{'Volume':[0.05,False],'Mean':[1000.,False],'StdDev':[300.,False],},
2873                'Unified':{'G':[1.e3,False],'Rg':[100,False],'B':[1.e-5,False],'P':[4,False],'Cutoff':[1e-5,False],},
2874                'Porod':{'B':[1.e-4,False],'P':[4,False],'Cutoff':[1e-5,False],},
2875                'Monodisperse':{'Volume':[0.05,False],'Radius':[100,False],},   #OK for spheres
2876                'Bragg':{'PkInt':[100,False],'PkPos':[0.2,False],
2877                    'PkSig':[10,False],'PkGam':[10,False],},        #reasonable 31A peak
2878                })
2879            G2sasd.ModelFxn(Profile,ProfDict,Limits,Sample,data)
2880            RefreshPlots(True)
2881                   
2882        wx.CallAfter(UpdateModelsGrid,G2frame,data)
2883       
2884    def OnCopyModel(event):
2885        hst = G2frame.PatternTree.GetItemText(G2frame.PatternId)
2886        histList = GetHistsLikeSelected(G2frame)
2887        if not histList:
2888            G2frame.ErrorDialog('No match','No histograms match '+hst,G2frame.dataFrame)
2889            return
2890        copyList = []
2891        dlg = G2gd.G2MultiChoiceDialog(
2892            G2frame.dataFrame, 
2893            'Copy models from\n'+hst[5:]+' to...',
2894            'Copy models', histList)
2895        try:
2896            if dlg.ShowModal() == wx.ID_OK:
2897                for i in dlg.GetSelections(): 
2898                    copyList.append(histList[i])
2899        finally:
2900            dlg.Destroy()       
2901        for item in copyList:
2902            Id = G2gd.GetPatternTreeItemId(G2frame,G2frame.root,item)
2903            newdata = copy.deepcopy(data)
2904            G2frame.PatternTree.SetItemPyData(G2gd.GetPatternTreeItemId(G2frame,Id,'Models'),newdata)
2905            if newdata['BackFile']:
2906                Profile = G2frame.PatternTree.GetItemPyData(Id)[1]
2907                BackId = G2gd.GetPatternTreeItemId(G2frame,G2frame.root,newdata['BackFile'])
2908                BackSample = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,BackId, 'Sample Parameters'))
2909                Profile[5] = BackSample['Scale'][0]*G2frame.PatternTree.GetItemPyData(BackId)[1][1]
2910        RefreshPlots(True)
2911               
2912    def OnCopyFlags(event):
2913        thisModel = copy.deepcopy(data)
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        dlg = G2gd.G2MultiChoiceDialog(
2920            G2frame.dataFrame, 
2921            'Copy sample ref. flags from\n'+str(hst[5:])+' to...',
2922            'Copy sample flags', histList)
2923        distChoice = ['LogNormal','Gaussian','LSW','Schulz-Zimm','Bragg','Unified',
2924            'Porod','Monodisperse',]
2925        parmOrder = ['Volume','Radius','Mean','StdDev','G','Rg','B','P',
2926            'Cutoff','PkInt','PkPos','PkSig','PkGam','VolFr','Dist',]
2927        try:
2928            if dlg.ShowModal() == wx.ID_OK:
2929                result = dlg.GetSelections()
2930                for i in result: 
2931                    item = histList[i]
2932                    Id = G2gd.GetPatternTreeItemId(G2frame,G2frame.root,item)
2933                    newModel = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,Id,'Models'))
2934                    newModel['Back'][1] = copy.copy(thisModel['Back'][1])
2935                    for ilev,level in enumerate(newModel['Particle']['Levels']):
2936                        for form in level:
2937                            if form in distChoice:
2938                                thisForm = thisModel['Particle']['Levels'][ilev][form]                               
2939                                for item in parmOrder:
2940                                    if item in thisForm:
2941                                       level[form][item][1] = copy.copy(thisForm[item][1])
2942                            elif form == 'Controls':
2943                                thisForm = thisModel['Particle']['Levels'][ilev][form]['SFargs']
2944                                for item in parmOrder:
2945                                    if item in thisForm:
2946                                        level[form]['SFargs'][item][1] = copy.copy(thisForm[item][1])
2947        finally:
2948            dlg.Destroy()
2949               
2950    def OnFitModelAll(event):
2951        choices = G2gd.GetPatternTreeDataNames(G2frame,['SASD',])
2952        sel = []
2953        dlg = G2gd.G2MultiChoiceDialog(G2frame.dataFrame, 'Sequential SASD refinement',
2954             'Select dataset to include',choices)
2955        dlg.SetSelections(sel)
2956        names = []
2957        if dlg.ShowModal() == wx.ID_OK:
2958            for sel in dlg.GetSelections():
2959                names.append(choices[sel])
2960        dlg.Destroy()
2961        SeqResult = {'histNames':names}
2962        Reverse = False
2963        CopyForward = False
2964        choice = ['Reverse sequence','Copy from prev.']
2965        dlg = wx.MultiChoiceDialog(G2frame.dataFrame,'Sequential controls','Select controls',choice)
2966        if dlg.ShowModal() == wx.ID_OK:
2967            for sel in dlg.GetSelections():
2968                if sel:
2969                    CopyForward = True
2970                else:
2971                    Reverse = True
2972        dlg.Destroy()
2973        dlg = wx.ProgressDialog('SASD Sequential fit','Data set name = '+names[0],len(names), 
2974            style = wx.PD_ELAPSED_TIME|wx.PD_AUTO_HIDE|wx.PD_REMAINING_TIME|wx.PD_CAN_ABORT)
2975        wx.BeginBusyCursor()
2976        if Reverse:
2977            names.reverse()
2978        try:
2979            for i,name in enumerate(names):
2980                print ' Sequential fit for ',name
2981                GoOn = dlg.Update(i,newmsg='Data set name = '+name)[0]
2982                if not GoOn:
2983                    break
2984                Id =  G2gd.GetPatternTreeItemId(G2frame,G2frame.root,name)
2985                if i and CopyForward:
2986                    G2frame.PatternTree.SetItemPyData(G2gd.GetPatternTreeItemId(G2frame,Id, 'Models'),JModel)
2987                IProfDict,IProfile = G2frame.PatternTree.GetItemPyData(Id)[:2]
2988                IModel = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,Id, 'Models'))
2989                ISample = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,Id, 'Sample Parameters'))
2990                ILimits = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,Id, 'Limits'))
2991                IInst = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,Id, 'Instrument Parameters'))
2992                IfOK,result,varyList,sig,Rvals,covMatrix,parmDict,Msg = G2sasd.ModelFit(IProfile,IProfDict,ILimits,ISample,IModel)
2993                JModel = copy.deepcopy(IModel)
2994                if not IfOK:
2995                    G2frame.ErrorDialog('Failed sequential refinement for data '+name,
2996                        ' Msg: '+Msg+'\nYou need to rethink your selection of parameters\n'+    \
2997                        ' Model restored to previous version for'+name)
2998                    SeqResult['histNames'] = names[:i]
2999                    dlg.Destroy()
3000                    break
3001                else:
3002                    G2frame.PatternTree.SetItemPyData(G2gd.GetPatternTreeItemId(G2frame,Id, 'Models'),copy.deepcopy(IModel))
3003               
3004                G2sasd.ModelFxn(IProfile,IProfDict,ILimits,ISample,IModel)
3005                SeqResult[name] = {'variables':result[0],'varyList':varyList,'sig':sig,'Rvals':Rvals,
3006                    'covMatrix':covMatrix,'title':name,'parmDict':parmDict}
3007            else:
3008                dlg.Destroy()
3009                print ' ***** Small angle sequential refinement successful *****'
3010        finally:
3011            wx.EndBusyCursor()   
3012        Id =  G2gd.GetPatternTreeItemId(G2frame,G2frame.root,'Sequential results')
3013        if Id:
3014            G2frame.PatternTree.SetItemPyData(Id,SeqResult)
3015        else:
3016            Id = G2frame.PatternTree.AppendItem(parent=G2frame.root,text='Sequential results')
3017            G2frame.PatternTree.SetItemPyData(Id,SeqResult)
3018        G2frame.PatternTree.SelectItem(Id)
3019       
3020    def OnFitModel(event):
3021        if data['Current'] == 'Size dist.':
3022            if not any(Sample['Contrast']):
3023                G2frame.ErrorDialog('No contrast; your sample is a vacuum!',
3024                    'You need to define a scattering substance!\n'+    \
3025                    ' Do Substances and then Sample parameters')
3026                return
3027            G2sasd.SizeDistribution(Profile,ProfDict,Limits,Sample,data)
3028            G2plt.PlotSASDSizeDist(G2frame)
3029            RefreshPlots(True)
3030           
3031        elif data['Current'] == 'Particle fit':
3032            SaveState()
3033            Results = G2sasd.ModelFit(Profile,ProfDict,Limits,Sample,data)
3034            if not Results[0]:
3035                    G2frame.ErrorDialog('Failed refinement',
3036                        ' Msg: '+Results[-1]+'\nYou need to rethink your selection of parameters\n'+    \
3037                        ' Model restored to previous version')
3038            G2sasd.ModelFxn(Profile,ProfDict,Limits,Sample,data)
3039            RefreshPlots(True)
3040            wx.CallAfter(UpdateModelsGrid,G2frame,data)
3041           
3042    def OnUnDo(event):
3043        DoUnDo()
3044        data = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,
3045            G2frame.PatternId,'Models'))
3046        G2frame.dataFrame.SasdUndo.Enable(False)
3047        UpdateModelsGrid(G2frame,data)
3048        G2sasd.ModelFxn(Profile,ProfDict,Limits,Sample,data)
3049        RefreshPlots(True)
3050
3051    def DoUnDo():
3052        print 'Undo last refinement'
3053        file = open(G2frame.undosasd,'rb')
3054        PatternId = G2frame.PatternId
3055        G2frame.PatternTree.SetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId, 'Models'),cPickle.load(file))
3056        print ' Models recovered'
3057        file.close()
3058       
3059    def SaveState():
3060        G2frame.undosasd = os.path.join(G2frame.dirname,'GSASIIsasd.save')
3061        file = open(G2frame.undosasd,'wb')
3062        PatternId = G2frame.PatternId
3063        for item in ['Models']:
3064            cPickle.dump(G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId,item)),file,1)
3065        file.close()
3066        G2frame.dataFrame.SasdUndo.Enable(True)
3067       
3068    def OnSelectFit(event):
3069        data['Current'] = fitSel.GetValue()
3070        wx.CallAfter(UpdateModelsGrid,G2frame,data)
3071       
3072    def OnCheckBox(event):
3073        Obj = event.GetEventObject()
3074        item,ind = Indx[Obj.GetId()]
3075        item[ind] = Obj.GetValue()
3076       
3077    def OnIntVal(event):
3078        Obj = event.GetEventObject()
3079        item,ind,minVal = Indx[Obj.GetId()]
3080        try:
3081            value = int(Obj.GetValue())
3082            if value <= minVal:
3083                raise ValueError
3084        except ValueError:
3085            value = item[ind]
3086        Obj.SetValue(str(value))
3087        item[ind] = value
3088
3089    def SizeSizer():
3090       
3091        def OnShape(event):
3092            data['Size']['Shape'][0] = partsh.GetValue()
3093            wx.CallAfter(UpdateModelsGrid,G2frame,data)
3094           
3095        def OnMethod(event):
3096            data['Size']['Method'] = method.GetValue()
3097            wx.CallAfter(UpdateModelsGrid,G2frame,data)
3098           
3099        def OnPartVal(event):
3100            try:
3101                val = max(0.0,float(partprm.GetValue()))
3102            except ValueError:
3103                val = 1
3104            data['Size']['Shape'][1] = val
3105            partprm.SetValue('%.3f'%(val))
3106           
3107        sizeSizer = wx.BoxSizer(wx.VERTICAL)
3108        sizeSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Size distribution parameters: '),0,WACV)
3109        binSizer = wx.FlexGridSizer(0,7,5,5)
3110        binSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' No. size bins: '),0,WACV)
3111        bins = ['50','100','150','200']
3112        nbins = wx.ComboBox(G2frame.dataDisplay,value=str(data['Size']['Nbins']),choices=bins,
3113            style=wx.CB_READONLY|wx.CB_DROPDOWN)
3114        Indx[nbins.GetId()] = [data['Size'],'Nbins',0]
3115        nbins.Bind(wx.EVT_COMBOBOX,OnIntVal)       
3116        binSizer.Add(nbins,0,WACV)
3117        binSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Min diam.: '),0,WACV)
3118        minDias = ['10','25','50','100','150','200']
3119        mindiam = wx.ComboBox(G2frame.dataDisplay,value=str(data['Size']['MinDiam']),choices=minDias,
3120            style=wx.CB_DROPDOWN)
3121        mindiam.Bind(wx.EVT_LEAVE_WINDOW,OnIntVal)
3122        mindiam.Bind(wx.EVT_TEXT_ENTER,OnIntVal)       
3123        mindiam.Bind(wx.EVT_KILL_FOCUS,OnIntVal)
3124        Indx[mindiam.GetId()] = [data['Size'],'MinDiam',0]
3125        binSizer.Add(mindiam,0,WACV)
3126        binSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Max diam.: '),0,WACV)
3127        maxDias = [str(1000*(i+1)) for i in range(10)]
3128        maxdiam = wx.ComboBox(G2frame.dataDisplay,value=str(data['Size']['MaxDiam']),choices=maxDias,
3129            style=wx.CB_DROPDOWN)
3130        maxdiam.Bind(wx.EVT_LEAVE_WINDOW,OnIntVal)
3131        maxdiam.Bind(wx.EVT_TEXT_ENTER,OnIntVal)       
3132        maxdiam.Bind(wx.EVT_KILL_FOCUS,OnIntVal)
3133        Indx[maxdiam.GetId()] = [data['Size'],'MaxDiam',0]
3134        binSizer.Add(maxdiam,0,WACV)
3135        logbins = wx.CheckBox(G2frame.dataDisplay,label='Log bins?')
3136        Indx[logbins.GetId()] = [data['Size'],'logBins']
3137        logbins.SetValue(data['Size']['logBins'])
3138        logbins.Bind(wx.EVT_CHECKBOX, OnCheckBox)
3139        binSizer.Add(logbins,0,WACV)
3140        sizeSizer.Add(binSizer,0)
3141        sizeSizer.Add((5,5),0)
3142        partSizer = wx.BoxSizer(wx.HORIZONTAL)
3143        partSizer.Add(wx.StaticText(G2frame.dataDisplay,label='Particle description: '),0,WACV)
3144        shapes = {'Spheroid':' Aspect ratio: ','Cylinder':' Diameter ','Cylinder AR':' Aspect ratio: ',
3145            'Unified sphere':'','Unified rod':' Diameter: ','Unified rod AR':' Aspect ratio: ',
3146            'Unified disk':' Thickness: '}
3147        partsh = wx.ComboBox(G2frame.dataDisplay,value=str(data['Size']['Shape'][0]),choices=shapes.keys(),
3148            style=wx.CB_READONLY|wx.CB_DROPDOWN)
3149        partsh.Bind(wx.EVT_COMBOBOX,OnShape)       
3150        partSizer.Add(partsh,0,WACV)
3151        if data['Size']['Shape'][0] not in ['Unified sphere',]:
3152            partSizer.Add(wx.StaticText(G2frame.dataDisplay,label=shapes[data['Size']['Shape'][0]]),0,WACV)
3153            partprm = wx.TextCtrl(G2frame.dataDisplay,value='%.3f'%(data['Size']['Shape'][1]),
3154                style=wx.TE_PROCESS_ENTER)
3155            partprm.Bind(wx.EVT_TEXT_ENTER,OnPartVal)       
3156            partprm.Bind(wx.EVT_KILL_FOCUS,OnPartVal)
3157            partSizer.Add(partprm,0,WACV)
3158        sizeSizer.Add(partSizer,0)
3159        sizeSizer.Add((5,5),0)
3160        fitSizer = wx.BoxSizer(wx.HORIZONTAL)
3161        methods = ['MaxEnt','IPG',]
3162        fitSizer.Add(wx.StaticText(G2frame.dataDisplay,label='Fitting method: '),0,WACV)
3163        method = wx.ComboBox(G2frame.dataDisplay,value=data['Size']['Method'],choices=methods,
3164            style=wx.CB_READONLY|wx.CB_DROPDOWN)
3165        method.Bind(wx.EVT_COMBOBOX,OnMethod)
3166        fitSizer.Add(method,0,WACV)
3167        iters = ['10','25','50','100','150','200']       
3168        fitSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' No. iterations: '),0,WACV)
3169        Method = data['Size']['Method']
3170        iter = wx.ComboBox(G2frame.dataDisplay,value=str(data['Size'][Method]['Niter']),choices=iters,
3171            style=wx.CB_READONLY|wx.CB_DROPDOWN)
3172        Indx[iter.GetId()] = [data['Size'][Method],'Niter',0]
3173        iter.Bind(wx.EVT_COMBOBOX,OnIntVal)
3174        fitSizer.Add(iter,0,WACV)
3175        if 'MaxEnt' in data['Size']['Method']:
3176            fitSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Log floor factor: '),0,WACV)
3177            floors = [str(-i) for i in range(9)]
3178            floor = wx.ComboBox(G2frame.dataDisplay,value=str(data['Size']['MaxEnt']['Sky']),choices=floors,
3179                style=wx.CB_READONLY|wx.CB_DROPDOWN)
3180            Indx[floor.GetId()] = [data['Size']['MaxEnt'],'Sky',-10]
3181            floor.Bind(wx.EVT_COMBOBOX,OnIntVal)
3182            fitSizer.Add(floor,0,WACV)
3183        elif 'IPG' in data['Size']['Method']:
3184            fitSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Q power weight (-1 for sigma): '),0,WACV)
3185            choices = ['-1','0','1','2','3','4']
3186            power = wx.ComboBox(G2frame.dataDisplay,value=str(data['Size']['IPG']['Power']),choices=choices,
3187                style=wx.CB_READONLY|wx.CB_DROPDOWN)
3188            Indx[power.GetId()] = [data['Size']['IPG'],'Power',-2]
3189            power.Bind(wx.EVT_COMBOBOX,OnIntVal)
3190            fitSizer.Add(power,0,WACV)
3191        sizeSizer.Add(fitSizer,0)
3192
3193        return sizeSizer
3194       
3195    def PartSizer():
3196       
3197        FormFactors = {'Sphere':{},'Spheroid':{'Aspect ratio':[1.0,False]},
3198            'Cylinder':{'Length':[100.,False]},'Cylinder diam':{'Diameter':[100.,False]},
3199            'Cylinder AR':{'Aspect ratio':[1.0,False]},'Unified sphere':{},
3200            'Unified rod':{'Length':[100.,False]},'Unified rod AR':{'Aspect ratio':[1.0,False]},
3201            'Unified disk':{'Thickness':[100.,False]},
3202            'Unified tube':{'Length':[100.,False],'Thickness':[10.,False]},}
3203               
3204        StructureFactors = {'Dilute':{},'Hard sphere':{'VolFr':[0.1,False],'Dist':[100.,False]},
3205            'Sticky hard sphere':{'VolFr':[0.1,False],'Dist':[100.,False],'epis':[0.05,False],'Sticky':[0.2,False]},
3206            'Square well':{'VolFr':[0.1,False],'Dist':[100.,False],'Depth':[0.1,False],'Width':[1.,False]},
3207            'InterPrecipitate':{'VolFr':[0.1,False],'Dist':[100.,False]},}
3208               
3209        ffDistChoices =  ['Sphere','Spheroid','Cylinder','Cylinder diam',
3210            'Cylinder AR','Unified sphere','Unified rod','Unified rod AR',
3211            'Unified disk','Unified tube',]
3212               
3213        ffMonoChoices = ['Sphere','Spheroid','Cylinder','Cylinder AR',]
3214       
3215        sfChoices = ['Dilute','Hard sphere','Sticky hard sphere','Square well','InterPrecipitate',]
3216           
3217        slMult = 1000.
3218                 
3219        def OnValue(event):
3220            Obj = event.GetEventObject()
3221            item,key,sldrObj = Indx[Obj.GetId()]
3222            try:
3223                value = float(Obj.GetValue())
3224                if value <= 0.:
3225                    raise ValueError
3226            except ValueError:
3227                value = item[key][0]
3228            item[key][0] = value
3229            Obj.SetValue('%.3g'%(value))
3230            if key in ['P','epis','Sticky','Depth','Width','VolFr','Dist']:
3231                sldrObj.SetValue(slMult*value)
3232            else:
3233                logv = np.log10(value)
3234                valMinMax = [logv-1,logv+1]
3235                sldrObj.SetRange(slMult*valMinMax[0],slMult*valMinMax[1])
3236                sldrObj.SetValue(slMult*logv)
3237            G2sasd.ModelFxn(Profile,ProfDict,Limits,Sample,data)
3238            RefreshPlots()
3239           
3240        def OnSelect(event):
3241            Obj = event.GetEventObject()
3242            item,key = Indx[Obj.GetId()]
3243            item[key] = Obj.GetValue()
3244            if 'Refine' not in Obj.GetLabel():
3245                if 'FormFact' in key :
3246                    item['FFargs'] = FormFactors[Obj.GetValue()]
3247                elif 'StrFact' in key:
3248                    item['SFargs'] = StructureFactors[Obj.GetValue()]
3249                wx.CallAfter(UpdateModelsGrid,G2frame,data)
3250                G2sasd.ModelFxn(Profile,ProfDict,Limits,Sample,data)
3251                RefreshPlots()
3252               
3253        def OnDelLevel(event):
3254            Obj = event.GetEventObject()
3255            item = Indx[Obj.GetId()]
3256            del data['Particle']['Levels'][item]
3257            wx.CallAfter(UpdateModelsGrid,G2frame,data)
3258            G2sasd.ModelFxn(Profile,ProfDict,Limits,Sample,data)
3259            RefreshPlots()
3260           
3261        def OnParmSlider(event):
3262            Obj = event.GetEventObject()
3263            item,key,pvObj = Indx[Obj.GetId()]
3264            slide = Obj.GetValue()
3265            if key in ['P','epis','Sticky','Depth','Width','VolFr','Dist']:
3266                value = float(slide/slMult)
3267            else:
3268                value = 10.**float(slide/slMult)
3269            item[key][0] = value
3270            pvObj.SetValue('%.3g'%(item[key][0]))
3271            G2sasd.ModelFxn(Profile,ProfDict,Limits,Sample,data)
3272            RefreshPlots()
3273           
3274        def SizeSizer():
3275            sizeSizer = wx.FlexGridSizer(0,4,5,5)
3276            sizeSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Distribution: '),0,WACV)
3277            Distchoice = ['LogNormal','Gaussian','LSW','Schulz-Zimm','Bragg','Unified','Porod','Monodisperse',]
3278            distChoice = wx.ComboBox(G2frame.dataDisplay,value=level['Controls']['DistType'],choices=Distchoice,
3279                style=wx.CB_READONLY|wx.CB_DROPDOWN)
3280            Indx[distChoice.GetId()] = [level['Controls'],'DistType']
3281            distChoice.Bind(wx.EVT_COMBOBOX,OnSelect)
3282            sizeSizer.Add(distChoice,0,WACV)    #put structure factor choices here
3283            if level['Controls']['DistType'] not in ['Bragg','Unified','Porod',]:
3284                sizeSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Form Factor: '),0,WACV)
3285                if 'Mono' in level['Controls']['DistType']:
3286                    ffChoice = wx.ComboBox(G2frame.dataDisplay,value=level['Controls']['FormFact'],choices=ffMonoChoices,
3287                        style=wx.CB_READONLY|wx.CB_DROPDOWN)
3288                else:
3289                    ffChoice = wx.ComboBox(G2frame.dataDisplay,value=level['Controls']['FormFact'],choices=ffDistChoices,
3290                        style=wx.CB_READONLY|wx.CB_DROPDOWN)
3291                Indx[ffChoice.GetId()] = [level['Controls'],'FormFact']
3292                ffChoice.Bind(wx.EVT_COMBOBOX,OnSelect)
3293                sizeSizer.Add(ffChoice,0,WACV)
3294               
3295                sizeSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Material: '),0,WACV)
3296                matSel = wx.ComboBox(G2frame.dataDisplay,value=level['Controls']['Material'],
3297                    choices=Substances['Substances'].keys(),style=wx.CB_READONLY|wx.CB_DROPDOWN)
3298                Indx[matSel.GetId()] = [level['Controls'],'Material']
3299                matSel.Bind(wx.EVT_COMBOBOX,OnSelect)       
3300                sizeSizer.Add(matSel,0,WACV) #do neutron test here?
3301                rho = Substances['Substances'][level['Controls']['Material']].get('XAnom density',0.0)
3302                level['Controls']['Contrast'] = contrast = (rho-rhoMat)**2                 
3303                sizeSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Resonant X-ray contrast: '),0,WACV)
3304                sizeSizer.Add(wx.StaticText(G2frame.dataDisplay,label=%.2f 10%scm%s'%(contrast,Pwr20,Pwrm4)),0,WACV)
3305                if 'Mono' not in level['Controls']['DistType']:
3306                    sizeSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Num. radii: '),0,WACV)
3307                    radii = ['25','50','75','100','200']
3308                    nRadii = wx.ComboBox(G2frame.dataDisplay,value=str(level['Controls']['NumPoints']),choices=radii,
3309                        style=wx.CB_READONLY|wx.CB_DROPDOWN)
3310                    Indx[nRadii.GetId()] = [level['Controls'],'NumPoints']
3311                    nRadii.Bind(wx.EVT_COMBOBOX,OnSelect)
3312                    sizeSizer.Add(nRadii,0,WACV)
3313                    sizeSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' R dist. cutoff: '),0,WACV)
3314                    rCutoff = G2gd.ValidatedTxtCtrl(G2frame.dataDisplay,level['Controls'],'Cutoff',
3315                        min=0.001,max=0.1,typeHint=float)
3316                    sizeSizer.Add(rCutoff,0,WACV)
3317            elif level['Controls']['DistType']  in ['Unified',]:
3318                Parms = level['Unified']
3319                Best = G2sasd.Bestimate(Parms['G'][0],Parms['Rg'][0],Parms['P'][0])
3320                sizeSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Estimated Dist B: %12.4g'%(Best)),0,WACV)
3321            return sizeSizer
3322           
3323        def ParmSizer():
3324            parmSizer = wx.FlexGridSizer(0,3,5,5)
3325            parmSizer.AddGrowableCol(2,1)
3326            parmSizer.SetFlexibleDirection(wx.HORIZONTAL)
3327            Parms = level[level['Controls']['DistType']]
3328            FFargs = level['Controls']['FFargs']
3329            SFargs = level['Controls'].get('SFargs',{})
3330            parmOrder = ['Volume','Radius','Mean','StdDev','MinSize','G','Rg','B','P','Cutoff',
3331                'PkInt','PkPos','PkSig','PkGam',]
3332            for parm in parmOrder:
3333                if parm in Parms:
3334                    if parm == 'MinSize':
3335                        parmSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Dist '+parm),0,wx.ALIGN_CENTER)
3336                    else:
3337                        parmVar = wx.CheckBox(G2frame.dataDisplay,label='Refine? Dist '+parm) 
3338                        parmVar.SetValue(Parms[parm][1])
3339                        parmVar.Bind(wx.EVT_CHECKBOX, OnSelect)
3340                        parmSizer.Add(parmVar,0,WACV)
3341                        Indx[parmVar.GetId()] = [Parms[parm],1]
3342                    parmValue = wx.TextCtrl(G2frame.dataDisplay,value='%.3g'%(Parms[parm][0]),
3343                        style=wx.TE_PROCESS_ENTER)
3344                    parmValue.Bind(wx.EVT_TEXT_ENTER,OnValue)       
3345                    parmValue.Bind(wx.EVT_KILL_FOCUS,OnValue)
3346                    parmSizer.Add(parmValue,0,WACV)
3347                    if parm == 'P':
3348                        value = Parms[parm][0]
3349                        valMinMax = [0.1,4.2]
3350                    else:
3351                        value = np.log10(Parms[parm][0])
3352                        valMinMax = [value-1,value+1]
3353                    parmSldr = wx.Slider(G2frame.dataDisplay,minValue=slMult*valMinMax[0],
3354                        maxValue=slMult*valMinMax[1],value=slMult*value)
3355                    Indx[parmValue.GetId()] = [Parms,parm,parmSldr]
3356                    Indx[parmSldr.GetId()] = [Parms,parm,parmValue]
3357                    parmSldr.Bind(wx.EVT_SLIDER,OnParmSlider)
3358                    parmSizer.Add(parmSldr,1,wx.EXPAND)
3359            if level['Controls']['DistType'] not in ['Bragg']:
3360                parmOrder = ['Aspect ratio','Length','Diameter','Thickness','VolFr','Dist','epis','Sticky','Depth','Width']
3361                fTypes = ['FF ','SF ']
3362                for iarg,Args in enumerate([FFargs,SFargs]):
3363                    for parm in parmOrder:
3364                        if parm in Args:
3365                            parmVar = wx.CheckBox(G2frame.dataDisplay,label='Refine? '+fTypes[iarg]+parm) 
3366                            parmVar.SetValue(Args[parm][1])
3367                            Indx[parmVar.GetId()] = [Args[parm],1]
3368                            parmVar.Bind(wx.EVT_CHECKBOX, OnSelect)
3369                            parmSizer.Add(parmVar,0,WACV)
3370                            parmValue = wx.TextCtrl(G2frame.dataDisplay,value='%.3g'%(Args[parm][0]),
3371                                style=wx.TE_PROCESS_ENTER)
3372                            parmValue.Bind(wx.EVT_TEXT_ENTER,OnValue)       
3373                            parmValue.Bind(wx.EVT_KILL_FOCUS,OnValue)
3374                            parmSizer.Add(parmValue,0,WACV)
3375                            value = Args[parm][0]
3376                            if parm == 'epis':
3377                                valMinMax = [0,.1]
3378                            elif parm in ['Sticky','Width',]:
3379                                valMinMax = [0,1.]
3380                            elif parm == 'Depth':
3381                                valMinMax = [-2.,2.]
3382                            elif parm == 'Dist':
3383                                valMinMax = [100.,1000.]
3384                            elif parm == 'VolFr':
3385                                valMinMax = [1.e-4,1.]
3386                            else:
3387                                value = np.log10(Args[parm][0])
3388                                valMinMax = [value-1,value+1]
3389                            parmSldr = wx.Slider(G2frame.dataDisplay,minValue=slMult*valMinMax[0],
3390                                maxValue=slMult*valMinMax[1],value=slMult*value)
3391                            Indx[parmVar.GetId()] = [Args[parm],1]
3392                            Indx[parmValue.GetId()] = [Args,parm,parmSldr]
3393                            Indx[parmSldr.GetId()] = [Args,parm,parmValue]
3394                            parmSldr.Bind(wx.EVT_SLIDER,OnParmSlider)
3395                            parmSizer.Add(parmSldr,1,wx.EXPAND)
3396            return parmSizer               
3397           
3398        Indx = {}
3399        partSizer = wx.BoxSizer(wx.VERTICAL)
3400        topSizer = wx.BoxSizer(wx.HORIZONTAL)
3401        topSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Particle fit parameters: '),0,WACV)
3402        topSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Matrix: '),0,WACV)
3403        matsel = wx.ComboBox(G2frame.dataDisplay,value=data['Particle']['Matrix']['Name'],
3404            choices=Substances['Substances'].keys(),style=wx.CB_READONLY|wx.CB_DROPDOWN)
3405        Indx[matsel.GetId()] = [data['Particle']['Matrix'],'Name'] 
3406        matsel.Bind(wx.EVT_COMBOBOX,OnSelect) #Do neutron test here?
3407        rhoMat = Substances['Substances'][data['Particle']['Matrix']['Name']].get('XAnom density',0.0)       
3408        topSizer.Add(matsel,0,WACV)
3409        topSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Volume fraction: '),0,WACV)
3410        volfrac = G2gd.ValidatedTxtCtrl(G2frame.dataDisplay,data['Particle']['Matrix']['VolFrac'],0,
3411                typeHint=float)
3412        topSizer.Add(volfrac,0,WACV)
3413        volVar = wx.CheckBox(G2frame.dataDisplay,label=' Refine?')
3414        volVar.SetValue(data['Particle']['Matrix']['VolFrac'][1])
3415        Indx[volVar.GetId()] = [data['Particle']['Matrix']['VolFrac'],1]
3416        volVar.Bind(wx.EVT_CHECKBOX, OnSelect)
3417        topSizer.Add(volVar,0,WACV)
3418        partSizer.Add(topSizer,0,)
3419        for ilev,level in enumerate(data['Particle']['Levels']):
3420            G2gd.HorizontalLine(partSizer,G2frame.dataDisplay)
3421            topLevel = wx.BoxSizer(wx.HORIZONTAL)
3422            topLevel.Add(wx.StaticText(G2frame.dataDisplay,label=' Model component %d: '%(ilev)),0,WACV)
3423            delBtn = wx.Button(G2frame.dataDisplay,label=' Delete?')
3424            Indx[delBtn.GetId()] = ilev
3425            delBtn.Bind(wx.EVT_BUTTON,OnDelLevel)
3426            topLevel.Add(delBtn,0,WACV)
3427            partSizer.Add(topLevel,0)
3428            partSizer.Add(SizeSizer())
3429            if level['Controls']['DistType'] not in ['Bragg','Unified','Porod',]:
3430                topLevel.Add(wx.StaticText(G2frame.dataDisplay,label=' Structure factor: '),0,WACV)
3431                strfctr = wx.ComboBox(G2frame.dataDisplay,value=level['Controls']['StrFact'],
3432                    choices=sfChoices,style=wx.CB_READONLY|wx.CB_DROPDOWN)
3433                Indx[strfctr.GetId()] = [level['Controls'],'StrFact']
3434                strfctr.Bind(wx.EVT_COMBOBOX,OnSelect)
3435                topLevel.Add(strfctr,0,WACV)
3436            partSizer.Add(ParmSizer(),0,wx.EXPAND)
3437        return partSizer
3438       
3439    def OnEsdScale(event):
3440        try:
3441            value = float(esdScale.GetValue())
3442            if value <= 0.:
3443                raise ValueError
3444        except ValueError:
3445            value = 1./np.sqrt(ProfDict['wtFactor'])
3446        ProfDict['wtFactor'] = 1./value**2
3447        esdScale.SetValue('%.3f'%(value))
3448        RefreshPlots(True)
3449       
3450    def OnBackChange(event):
3451        try:
3452            value = float(backVal.GetValue())
3453        except ValueError:
3454            value = 0.0
3455        backVal.SetValue('%.3g'%(value))
3456        data['Back'][0] = value
3457        Profile[4][:] = value
3458        RefreshPlots()
3459       
3460    def OnBackFile(event):
3461        data['BackFile'] = backFile.GetValue()
3462        if data['BackFile']:
3463            fixBack =  data['Back'][0]
3464            BackId = G2gd.GetPatternTreeItemId(G2frame,G2frame.root,data['BackFile'])
3465            BackSample = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,BackId, 'Sample Parameters'))
3466            Profile[5] = BackSample['Scale'][0]*G2frame.PatternTree.GetItemPyData(BackId)[1][1]
3467            RefreshPlots(True)
3468           
3469    Sample = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,G2frame.PatternId, 'Sample Parameters'))
3470    Limits = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,G2frame.PatternId, 'Limits'))
3471    Inst = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,G2frame.PatternId, 'Instrument Parameters'))
3472    Substances = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,G2frame.PatternId, 'Substances'))
3473    ProfDict,Profile = G2frame.PatternTree.GetItemPyData(G2frame.PatternId)[:2]
3474    if data['BackFile']:
3475        BackId = G2gd.GetPatternTreeItemId(G2frame,G2frame.root,data['BackFile'])
3476        BackSample = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,BackId, 'Sample Parameters'))
3477        Profile[5] = BackSample['Scale'][0]*G2frame.PatternTree.GetItemPyData(BackId)[1][1]
3478    if G2frame.dataDisplay:
3479        G2frame.dataFrame.DestroyChildren()
3480    G2gd.SetDataMenuBar(G2frame,G2frame.dataFrame.ModelMenu)
3481    if not G2frame.dataFrame.GetStatusBar():
3482        Status = G2frame.dataFrame.CreateStatusBar()
3483    G2frame.dataFrame.SetLabel('Modelling')
3484    G2frame.dataDisplay = wxscroll.ScrolledPanel(G2frame.dataFrame)
3485    G2frame.dataFrame.Bind(wx.EVT_MENU, OnCopyModel, id=G2gd.wxID_MODELCOPY)
3486    G2frame.dataFrame.Bind(wx.EVT_MENU, OnCopyFlags, id=G2gd.wxID_MODELCOPYFLAGS)
3487    G2frame.dataFrame.Bind(wx.EVT_MENU, OnFitModel, id=G2gd.wxID_MODELFIT)
3488    G2frame.dataFrame.Bind(wx.EVT_MENU, OnFitModelAll, id=G2gd.wxID_MODELFITALL)
3489    G2frame.dataFrame.Bind(wx.EVT_MENU, OnUnDo, id=G2gd.wxID_MODELUNDO)
3490    G2frame.dataFrame.Bind(wx.EVT_MENU, OnAddModel, id=G2gd.wxID_MODELADD)
3491    Indx = {}
3492    mainSizer = wx.BoxSizer(wx.VERTICAL)
3493    topSizer = wx.BoxSizer(wx.HORIZONTAL)
3494    models = ['Size dist.','Particle fit']
3495    topSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Modeling by: '),0,WACV)
3496    fitSel = wx.ComboBox(G2frame.dataDisplay,value=data['Current'],choices=models,
3497        style=wx.CB_READONLY|wx.CB_DROPDOWN)
3498    fitSel.Bind(wx.EVT_COMBOBOX,OnSelectFit)       
3499    topSizer.Add(fitSel,0,WACV)
3500    topSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Error multiplier: '),0,WACV)
3501    esdScale = wx.TextCtrl(G2frame.dataDisplay,value='%.3f'%(1./np.sqrt(ProfDict['wtFactor'])),style=wx.TE_PROCESS_ENTER)
3502    esdScale.Bind(wx.EVT_TEXT_ENTER,OnEsdScale)       
3503    esdScale.Bind(wx.EVT_KILL_FOCUS,OnEsdScale)
3504    topSizer.Add(esdScale,0,WACV)
3505    mainSizer.Add(topSizer)
3506    G2gd.HorizontalLine(mainSizer,G2frame.dataDisplay)
3507    if 'Size' in data['Current']:
3508        if 'MaxEnt' in data['Size']['Method']:
3509            Status.SetStatusText('Size distribution by Maximum entropy')
3510        elif 'IPG' in data['Size']['Method']:
3511            Status.SetStatusText('Size distribution by Interior-Point Gradient')
3512        mainSizer.Add(SizeSizer())       
3513    elif 'Particle' in data['Current']:
3514        mainSizer.Add(PartSizer(),1,wx.ALIGN_LEFT|wx.EXPAND)
3515    G2gd.HorizontalLine(mainSizer,G2frame.dataDisplay)   
3516    backSizer = wx.BoxSizer(wx.HORIZONTAL)
3517    backSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Background:'),0,WACV)
3518    backVal = wx.TextCtrl(G2frame.dataDisplay,value='%.3g'%(data['Back'][0]),style=wx.TE_PROCESS_ENTER)
3519    Indx[backVal.GetId()] = ['Back',0,'%.3g']
3520    backVal.Bind(wx.EVT_TEXT_ENTER,OnBackChange)       
3521    backVal.Bind(wx.EVT_KILL_FOCUS,OnBackChange)
3522    backSizer.Add(backVal,0,WACV)
3523    backVar = wx.CheckBox(G2frame.dataDisplay,label='Refine?')
3524    Indx[backVar.GetId()] = [data['Back'],1]
3525    backVar.SetValue(data['Back'][1])
3526    backVar.Bind(wx.EVT_CHECKBOX, OnCheckBox)
3527    backSizer.Add(backVar,0,WACV)   
3528    backSizer.Add(wx.StaticText(G2frame.dataDisplay,-1,' Background file: '),0,WACV)
3529    Choices = ['',]+G2gd.GetPatternTreeDataNames(G2frame,['SASD',])
3530    backFile = wx.ComboBox(parent=G2frame.dataDisplay,value=data['BackFile'],choices=Choices,
3531        style=wx.CB_READONLY|wx.CB_DROPDOWN)
3532    backFile.Bind(wx.EVT_COMBOBOX,OnBackFile)
3533    backSizer.Add(backFile)   
3534    mainSizer.Add(backSizer)
3535
3536    mainSizer.Layout()   
3537    G2frame.dataDisplay.SetSizer(mainSizer)
3538    G2frame.dataDisplay.SetAutoLayout(1)
3539    G2frame.dataDisplay.SetupScrolling()
3540    Size = mainSizer.Fit(G2frame.dataFrame)
3541    Size[0] += 25
3542    G2frame.dataDisplay.SetSize(Size)
3543    G2frame.dataFrame.setSizePosLeft(Size)   
3544   
3545################################################################################
3546#####  PDF controls
3547################################################################################           
3548       
3549def UpdatePDFGrid(G2frame,data):
3550    '''respond to selection of PWDR PDF data tree item.
3551    '''
3552    global inst
3553    tth2q = lambda t,w:4.0*math.pi*sind(t/2.0)/w
3554    dataFile = G2frame.PatternTree.GetItemText(G2frame.PatternId)
3555    powName = 'PWDR'+dataFile[4:]
3556    powId = G2gd.GetPatternTreeItemId(G2frame,G2frame.root, powName)
3557    fullLimits,limits = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,powId, 'Limits'))[:2]
3558    inst = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,powId, 'Instrument Parameters'))[0]
3559    if 'Lam' in inst:
3560        keV = 12.397639/inst['Lam'][1]
3561    else:
3562        keV = 12.397639/inst['Lam1'][0]
3563    wave = 12.397639/keV
3564    qLimits = [tth2q(fullLimits[0],wave),tth2q(fullLimits[1],wave)]
3565    data['QScaleLim'][1] = min(qLimits[1],data['QScaleLim'][1])
3566    if data['QScaleLim'][0]:
3567        data['QScaleLim'][0] = max(qLimits[0],data['QScaleLim'][0])
3568    else:                                #initial setting at 90% of max Q
3569        data['QScaleLim'][0] = 0.90*data['QScaleLim'][1]
3570    polariz = inst['Polariz.'][1]
3571    azimuth = inst['Azimuth'][1]
3572    itemDict = {}
3573   
3574    def FillFileSizer(fileSizer,key):
3575        #fileSizer is a FlexGridSizer(3,6)
3576       
3577        def OnSelectFile(event):
3578            Obj = event.GetEventObject()
3579            fileKey,itemKey,fmt = itemDict[Obj.GetId()]
3580            if itemKey == 'Name':
3581                value = Obj.GetValue()
3582            Obj.SetValue(fmt%(value))
3583            data[fileKey][itemKey] = value
3584            UpdatePDFGrid(G2frame,data)
3585       
3586        def OnValueChange(event):
3587            Obj = event.GetEventObject()
3588            fileKey,itemKey,fmt = itemDict[Obj.GetId()]
3589            try:
3590                value = float(Obj.GetValue())
3591            except ValueError:
3592                value = -1.0
3593            Obj.SetValue(fmt%(value))
3594            data[fileKey][itemKey] = value
3595            auxPlot = ComputePDF(data)
3596            G2plt.PlotISFG(G2frame,newPlot=True)
3597                       
3598        item = data[key]
3599        fileList = np.array(GetFileList('PWDR')).T[1]
3600        fileSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' '+key+' file:'),0,WACV)
3601        fileName = wx.ComboBox(G2frame.dataDisplay,value=item['Name'],choices=fileList,
3602            style=wx.CB_READONLY|wx.CB_DROPDOWN)
3603        itemDict[fileName.GetId()] = [key,'Name','%s']
3604        fileName.Bind(wx.EVT_COMBOBOX,OnSelectFile)       
3605        fileSizer.Add(fileName,0,)
3606        fileSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label='Multiplier:'),0,WACV)
3607        mult = wx.TextCtrl(G2frame.dataDisplay,value='%.3f'%(item['Mult']),style=wx.TE_PROCESS_ENTER)
3608        itemDict[mult.GetId()] = [key,'Mult','%.3f']
3609        mult.Bind(wx.EVT_TEXT_ENTER,OnValueChange)       
3610        mult.Bind(wx.EVT_KILL_FOCUS,OnValueChange)
3611        fileSizer.Add(mult,0,)
3612        fileSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label='Add:'),0,WACV)
3613        add = wx.TextCtrl(G2frame.dataDisplay,value='%.0f'%(item['Add']),style=wx.TE_PROCESS_ENTER)
3614        itemDict[add.GetId()] = [key,'Add','%.0f']
3615        add.Bind(wx.EVT_TEXT_ENTER,OnValueChange)       
3616        add.Bind(wx.EVT_KILL_FOCUS,OnValueChange)
3617        fileSizer.Add(add,0,)
3618       
3619    def SumElementVolumes():
3620        sumVol = 0.
3621        ElList = data['ElList']
3622        for El in ElList:
3623            Avol = (4.*math.pi/3.)*ElList[El]['Drad']**3
3624            sumVol += Avol*ElList[El]['FormulaNo']
3625        return sumVol
3626        auxPlot = ComputePDF(data)
3627        G2plt.PlotISFG(G2frame,newPlot=True)       
3628       
3629    def FillElemSizer(elemSizer,ElData):
3630       
3631        def OnFractionChange(event):
3632            try:
3633                value = max(0.0,float(num.GetValue()))
3634            except ValueError:
3635                value = 0.0
3636            num.SetValue('%.3f'%(value))
3637            ElData['FormulaNo'] = value
3638            data['Form Vol'] = max(10.0,SumElementVolumes())
3639            formVol.SetValue('%.2f'%(data['Form Vol']))
3640            wx.CallAfter(UpdatePDFGrid,G2frame,data)
3641            auxPlot = ComputePDF(data)
3642            G2plt.PlotISFG(G2frame,newPlot=True)       
3643       
3644        elemSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,
3645            label=' Element: '+'%2s'%(ElData['Symbol'])+' * '),0,WACV)
3646        num = wx.TextCtrl(G2frame.dataDisplay,value='%.3f'%(ElData['FormulaNo']),style=wx.TE_PROCESS_ENTER)
3647        num.Bind(wx.EVT_TEXT_ENTER,OnFractionChange)       
3648        num.Bind(wx.EVT_KILL_FOCUS,OnFractionChange)
3649        elemSizer.Add(num,0,WACV)
3650        elemSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,
3651            label="f': %.3f"%(ElData['fp'])+' f": %.3f'%(ElData['fpp'])+' mu: %.2f barns'%(ElData['mu']) ),
3652            0,WACV)
3653           
3654    def OnGeometry(event):
3655        data['Geometry'] = geometry.GetValue()
3656        UpdatePDFGrid(G2frame,data)
3657        auxPlot = ComputePDF(data)
3658        G2plt.PlotISFG(G2frame,newPlot=True)       
3659       
3660    def OnDetType(event):
3661        data['DetType'] = detType.GetValue()
3662        UpdatePDFGrid(G2frame,data)
3663        auxPlot = ComputePDF(data)
3664        G2plt.PlotISFG(G2frame,newPlot=True)       
3665       
3666    def OnFormVol(event):
3667        try:
3668            value = float(formVol.GetValue())
3669            if value <= 0.0:
3670                raise ValueError
3671        except ValueError:
3672            value = data['Form Vol']
3673        data['Form Vol'] = value
3674        UpdatePDFGrid(G2frame,data)
3675        auxPlot = ComputePDF(data)
3676        G2plt.PlotISFG(G2frame,newPlot=False)       
3677       
3678    def OnDiameter(event):
3679        try:
3680            value = float(diam.GetValue())
3681            if value <= 0.0:
3682                raise ValueError
3683        except ValueError:
3684            value = data['Diam']
3685        data['Diam'] = value
3686        UpdatePDFGrid(G2frame,data)
3687        auxPlot = ComputePDF(data)
3688        G2plt.PlotISFG(G2frame,newPlot=False)
3689       
3690    def OnPolaVal(event):
3691        try:
3692            value = float(polaVal.GetValue())
3693            if not (0.0 <= value <= 1.0):
3694                raise ValueError
3695        except ValueError:
3696            value = inst['Polariz.'][1]
3697        inst['Polariz.'][1] = value
3698        polaVal.SetValue('%.2f'%(inst['Polariz.'][1]))
3699        UpdatePDFGrid(G2frame,data)
3700        auxPlot = ComputePDF(data)
3701        G2plt.PlotISFG(G2frame,newPlot=False)
3702               
3703    def OnAzimVal(event):
3704        try:
3705            value = float(azimVal.GetValue())
3706            if not (0. <= value <= 360.):
3707                raise ValueError
3708        except ValueError:
3709            value = inst['Azimuth'][1]
3710        inst['Azimuth'][1] = value
3711        azimVal.SetValue('%.1f'%(inst['Azimuth'][1]))
3712        UpdatePDFGrid(G2frame,data)
3713        auxPlot = ComputePDF(data)
3714        G2plt.PlotISFG(G2frame,newPlot=False)
3715                       
3716    def OnObliqCoeff(event):
3717        try:
3718            value = float(obliqCoeff.GetValue())
3719            if value < 0.0:
3720                raise ValueError
3721            elif value > 1.0:
3722                value = 1.0
3723        except ValueError:
3724            value = data['ObliqCoeff']
3725        data['ObliqCoeff'] = value
3726        obliqCoeff.SetValue('%.3f'%(value))
3727        auxPlot = ComputePDF(data)
3728        G2plt.PlotISFG(G2frame,newPlot=False)
3729       
3730    def OnRulandWdt(event):
3731        try:
3732            value = float(rulandWdt.GetValue())
3733            if value <= 0.001:
3734                raise ValueError
3735            elif value > 1.0:
3736                value = 1.0
3737        except ValueError:
3738            value = data['Ruland']
3739        data['Ruland'] = value
3740        rulandWdt.SetValue('%.3f'%(value))
3741        auxPlot = ComputePDF(data)
3742        G2plt.PlotISFG(G2frame,newPlot=False)
3743       
3744    def OnRulSlider(event):
3745        value = int(rulandSldr.GetValue())/1000.
3746        data['Ruland'] = max(0.001,value)
3747        rulandWdt.SetValue('%.3f'%(data['Ruland']))
3748        auxPlot = ComputePDF(data)
3749        G2plt.PlotISFG(G2frame,newPlot=False)
3750       
3751    def OnLorch(event):
3752        data['Lorch'] = lorch.GetValue()
3753        auxPlot = ComputePDF(data)
3754        G2plt.PlotISFG(G2frame,newPlot=False)       
3755                       
3756    def OnPacking(event):
3757        try:
3758            value = float(pack.GetValue())
3759            if value <= 0.0:
3760                raise ValueError
3761        except ValueError:
3762            value = data['Pack']
3763        data['Pack'] = value
3764        UpdatePDFGrid(G2frame,data)
3765        auxPlot = ComputePDF(data)
3766        G2plt.PlotISFG(G2frame,newPlot=False)       
3767               
3768    def OnSQmin(event):
3769        try:
3770            value = float(SQmin.GetValue())
3771            if value < qLimits[0]:
3772                raise ValueError
3773        except ValueError:
3774            value = max(qLimits[0],data['QScaleLim'][0])
3775        data['QScaleLim'][0] = value
3776        SQmin.SetValue('%.1f'%(value))
3777        auxPlot = ComputePDF(data)
3778        G2plt.PlotISFG(G2frame,newPlot=True)       
3779       
3780    def OnSQmax(event):
3781        try:
3782            value = float(SQmax.GetValue())
3783            if value > qLimits[1]:
3784                raise ValueError
3785        except ValueError:
3786            value = min(qLimits[1],data['QScaleLim'][1])
3787        data['QScaleLim'][1] = value
3788        if value < data['QScaleLim'][0]:
3789            data['QScaleLim'][0] = 0.90*value
3790            SQmin.SetValue('%.1f'%(data['QScaleLim'][0]))
3791        SQmax.SetValue('%.1f'%(value))
3792        auxPlot = ComputePDF(data)
3793        G2plt.PlotISFG(G2frame,newPlot=True)
3794       
3795    def OnResetQ(event):
3796        resetQ.SetValue(False)
3797        data['QScaleLim'][1] = qLimits[1]
3798        SQmax.SetValue('%.1f'%(data['QScaleLim'][1]))
3799        data['QScaleLim'][0] = 0.9*qLimits[1]
3800        SQmin.SetValue('%.1f'%(data['QScaleLim'][0]))
3801        auxPlot = ComputePDF(data)
3802        G2plt.PlotISFG(G2frame,newPlot=True)       
3803
3804    def GetFileList(fileType,skip=None):
3805        fileList = [[False,'',0]]
3806        Source = ''
3807        id, cookie = G2frame.PatternTree.GetFirstChild(G2frame.root)
3808        while id:
3809            name = G2frame.PatternTree.GetItemText(id)
3810            if fileType in name:
3811                if id == skip:
3812                    Source = name
3813                else:
3814                    fileList.append([False,name,id])
3815            id, cookie = G2frame.PatternTree.GetNextChild(G2frame.root, cookie)
3816        if skip:
3817            return fileList,Source
3818        else:
3819            return fileList
3820       
3821    def OnCopyPDFControls(event):
3822        import copy
3823        TextList,Source = GetFileList('PDF',skip=G2frame.PatternId)
3824        TextList[0] = [False,'All PDF',0]
3825        if len(TextList) == 1:
3826            G2frame.ErrorDialog('Nothing to copy controls to','There must be more than one "PDF" pattern')
3827            return
3828        dlg = G2frame.CopyDialog(G2frame,'Copy PDF controls','Copy controls from '+Source+' to:',TextList)
3829        try:
3830            if dlg.ShowModal() == wx.ID_OK:
3831                result = dlg.GetData()
3832                if result[0][0]:
3833                    result = TextList[1:]
3834                    for item in result: item[0] = True
3835                for i,item in enumerate(result):
3836                    ifcopy,name,id = item
3837                    if ifcopy:
3838                        olddata = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,id, 'PDF Controls'))
3839                        sample = olddata['Sample']
3840                        olddata.update(copy.deepcopy(data))
3841                        olddata['Sample'] = sample
3842                        G2frame.PatternTree.SetItemPyData(G2gd.GetPatternTreeItemId(G2frame,id, 'PDF Controls'),olddata)
3843                Status.SetStatusText('PDF controls copied')
3844        finally:
3845            dlg.Destroy()
3846               
3847    def OnSavePDFControls(event):
3848        print 'save PDF controls?'
3849       
3850    def OnLoadPDFControls(event):
3851        print 'Load PDF controls?'
3852       
3853    def OnAddElement(event):
3854        ElList = data['ElList']
3855        PE = G2elemGUI.PickElement(G2frame,oneOnly=True)
3856        if PE.ShowModal() == wx.ID_OK:
3857            El = PE.Elem
3858            if El not in ElList and El != 'None':
3859                ElemSym = El.strip().capitalize()               
3860                FpMu = G2elem.FPcalc(G2elem.GetXsectionCoeff(ElemSym), keV)
3861                ElData = G2elem.GetFormFactorCoeff(ElemSym)[0]
3862                ElData['FormulaNo'] = 0.0
3863                ElData.update(G2elem.GetAtomInfo(ElemSym))
3864                ElData.update(dict(zip(['fp','fpp','mu'],FpMu)))
3865                ElData.update(G2elem.GetFFC5(El))
3866                data['ElList'][El] = ElData
3867            data['Form Vol'] = max(10.0,SumElementVolumes())
3868        PE.Destroy()
3869        UpdatePDFGrid(G2frame,data)
3870       
3871    def OnDeleteElement(event):
3872        ElList = data['ElList']
3873        choice = ElList.keys()
3874        dlg = G2elemGUI.DeleteElement(G2frame,choice=choice)
3875        if dlg.ShowModal() == wx.ID_OK:
3876            del ElList[dlg.GetDeleteElement()]
3877        dlg.Destroy()
3878        UpdatePDFGrid(G2frame,data)
3879               
3880    def ComputePDF(Data):
3881        xydata = {}
3882        for key in ['Sample','Sample Bkg.','Container','Container Bkg.']:
3883            name = Data[key]['Name']
3884            if name:
3885                xydata[key] = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,G2frame.root,name))
3886                PDFname = name
3887        powName = xydata['Sample'][2]
3888        powId = G2gd.GetPatternTreeItemId(G2frame,G2frame.root,powName)
3889        inst = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,powId,'Instrument Parameters'))[0]
3890        auxPlot = G2pwd.CalcPDF(Data,inst,xydata)
3891        PDFId = G2gd.GetPatternTreeItemId(G2frame,G2frame.root,'PDF '+powName[4:])
3892        G2frame.PatternTree.SetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PDFId,'I(Q)'+powName[4:]),xydata['IofQ'])
3893        G2frame.PatternTree.SetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PDFId,'S(Q)'+powName[4:]),xydata['SofQ'])
3894        G2frame.PatternTree.SetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PDFId,'F(Q)'+powName[4:]),xydata['FofQ'])
3895        G2frame.PatternTree.SetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PDFId,'G(R)'+powName[4:]),xydata['GofR'])
3896        return auxPlot
3897       
3898    def OnComputePDF(event):
3899        print 'Calculating PDF:'
3900        auxPlot = ComputePDF(data)
3901        print 'Done calculating PDF:'
3902        Status.SetStatusText('PDF computed')
3903        for plot in auxPlot:
3904            G2plt.PlotXY(G2frame,plot[:2],Title=plot[2])
3905       
3906        G2plt.PlotISFG(G2frame,newPlot=True,type='I(Q)')
3907        G2plt.PlotISFG(G2frame,newPlot=True,type='S(Q)')
3908        G2plt.PlotISFG(G2frame,newPlot=True,type='F(Q)')
3909        G2plt.PlotISFG(G2frame,newPlot=True,type='G(R)')
3910       
3911    def OnComputeAllPDF(event):
3912        print 'Calculating PDFs:'
3913        if G2frame.PatternTree.GetCount():
3914            id, cookie = G2frame.PatternTree.GetFirstChild(G2frame.root)
3915            while id:
3916                Name = G2frame.PatternTree.GetItemText(id)
3917                if 'PDF' in Name:
3918                    Data = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,id,'PDF Controls'))
3919                    auxPlot = ComputePDF(Data)                   
3920                id, cookie = G2frame.PatternTree.GetNextChild(G2frame.root, cookie)
3921            Status.SetStatusText('All PDFs computed')
3922            G2plt.PlotISFG(G2frame,newPlot=True,type='G(R)')
3923            print ' Done calculating PDFs:'
3924       
3925    def OnShowTip(G2frame,tip):
3926        print tip   
3927               
3928    if G2frame.dataDisplay:
3929        G2frame.dataFrame.Clear()
3930    G2gd.SetDataMenuBar(G2frame,G2frame.dataFrame.PDFMenu)
3931    if not G2frame.dataFrame.GetStatusBar():
3932        Status = G2frame.dataFrame.CreateStatusBar()   
3933    G2frame.dataDisplay = wx.Panel(G2frame.dataFrame)
3934    G2frame.dataFrame.Bind(wx.EVT_MENU, OnCopyPDFControls, id=G2gd.wxID_PDFCOPYCONTROLS)
3935    G2frame.dataFrame.Bind(wx.EVT_MENU, OnSavePDFControls, id=G2gd.wxID_PDFSAVECONTROLS)
3936    G2frame.dataFrame.Bind(wx.EVT_MENU, OnLoadPDFControls, id=G2gd.wxID_PDFLOADCONTROLS)
3937    G2frame.dataFrame.Bind(wx.EVT_MENU, OnAddElement, id=G2gd.wxID_PDFADDELEMENT)
3938    G2frame.dataFrame.Bind(wx.EVT_MENU, OnDeleteElement, id=G2gd.wxID_PDFDELELEMENT)
3939    G2frame.dataFrame.Bind(wx.EVT_MENU, OnComputePDF, id=G2gd.wxID_PDFCOMPUTE)
3940    G2frame.dataFrame.Bind(wx.EVT_MENU, OnComputeAllPDF, id=G2gd.wxID_PDFCOMPUTEALL)
3941    mainSizer = wx.BoxSizer(wx.VERTICAL)
3942    mainSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' PDF data files: '),0,WACV)
3943    mainSizer.Add((5,5),0)
3944    str = ' Sample file: PWDR %s   Wavelength, A: %.5f  Energy, keV: %.3f  Polariz.: %.2f '%(dataFile[3:],wave,keV,polariz)
3945    mainSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=str),0,WACV)
3946#    dataSizer = wx.BoxSizer(wx.HORIZONTAL)
3947#    dataSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label='Azimuth'),0,WACV)
3948#    azimVal = wx.TextCtrl(G2frame.dataDisplay,value='%.2f'%(inst['Azimuth']))
3949#    azimVal.Bind(wx.EVT_TEXT_ENTER,OnAzimVal)       
3950#    azimVal.Bind(wx.EVT_KILL_FOCUS,OnAzimVal)
3951#    dataSizer.Add(azimVal,0)   
3952#    dataSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label='Polarization'),0,WACV)
3953#    polaVal = wx.TextCtrl(G2frame.dataDisplay,value='%.2f'%(inst['Polariz.']))
3954#    polaVal.Bind(wx.EVT_TEXT_ENTER,OnPolaVal)       
3955#    polaVal.Bind(wx.EVT_KILL_FOCUS,OnPolaVal)
3956#    dataSizer.Add(polaVal,0)   
3957#    mainSizer.Add(dataSizer,0)
3958    mainSizer.Add((5,5),0)
3959    fileSizer = wx.FlexGridSizer(0,6,5,1)
3960    select = ['Sample Bkg.','Container']
3961    if data['Container']['Name']:
3962        select.append('Container Bkg.')
3963    for key in select:
3964        FillFileSizer(fileSizer,key)
3965    mainSizer.Add(fileSizer,0)
3966    mainSizer.Add((5,5),0)
3967    mainSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Sample information: '),0,WACV)
3968    mainSizer.Add((5,5),0)   
3969
3970    ElList = data['ElList']
3971    Abs = G2lat.CellAbsorption(ElList,data['Form Vol'])
3972    Trans = G2pwd.Transmission(data['Geometry'],Abs*data['Pack'],data['Diam'])
3973    elemSizer = wx.FlexGridSizer(0,3,5,1)
3974    for El in ElList:
3975        FillElemSizer(elemSizer,ElList[El])
3976    mainSizer.Add(elemSizer,0)
3977    mainSizer.Add((5,5),0)   
3978    midSizer = wx.BoxSizer(wx.HORIZONTAL)
3979    midSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Formula volume: '),0,WACV)
3980    formVol = wx.TextCtrl(G2frame.dataDisplay,value='%.2f'%(data['Form Vol']))
3981    formVol.Bind(wx.EVT_TEXT_ENTER,OnFormVol)       
3982    formVol.Bind(wx.EVT_KILL_FOCUS,OnFormVol)
3983    midSizer.Add(formVol,0)
3984    midSizer.Add(wx.StaticText(G2frame.dataDisplay,
3985        label=' Theoretical absorption: %.4f cm-1 Sample absorption: %.4f cm-1'%(Abs,Abs*data['Pack'])),
3986        0,WACV)
3987    mainSizer.Add(midSizer,0)
3988    mainSizer.Add((5,5),0)   
3989
3990    geoBox = wx.BoxSizer(wx.HORIZONTAL)
3991    geoBox.Add(wx.StaticText(G2frame.dataDisplay,label=' Sample geometry: '),0,WACV)
3992    choice = ['Cylinder','Bragg-Brentano','Tilting flat plate in transmission','Fixed flat plate']
3993    geometry = wx.ComboBox(G2frame.dataDisplay,value=data['Geometry'],choices=choice,
3994            style=wx.CB_READONLY|wx.CB_DROPDOWN)
3995    geometry.Bind(wx.EVT_COMBOBOX, OnGeometry)
3996    geoBox.Add(geometry,0)
3997    geoBox.Add(wx.StaticText(G2frame.dataDisplay,label=' Sample diameter/thickness, mm: '),0,WACV)
3998    diam = wx.TextCtrl(G2frame.dataDisplay,value='%.3f'%(data['Diam']))
3999    diam.Bind(wx.EVT_TEXT_ENTER,OnDiameter)       
4000    diam.Bind(wx.EVT_KILL_FOCUS,OnDiameter)
4001#    diam.Bind(wx.EVT_SET_FOCUS,OnShowTip(G2frame,'tip')) #this doesn't work - what would????
4002    geoBox.Add(diam,0)
4003    mainSizer.Add(geoBox,0)
4004    mainSizer.Add((5,5),0)   
4005    geoBox = wx.BoxSizer(wx.HORIZONTAL)
4006    geoBox.Add(wx.StaticText(G2frame.dataDisplay,label=' Packing: '),0,WACV)
4007    pack = wx.TextCtrl(G2frame.dataDisplay,value='%.2f'%(data['Pack']))
4008    pack.Bind(wx.EVT_TEXT_ENTER,OnPacking)       
4009    pack.Bind(wx.EVT_KILL_FOCUS,OnPacking)
4010    geoBox.Add(pack,0)
4011    geoBox.Add(wx.StaticText(G2frame.dataDisplay,label=' Sample transmission: %.3f %%'%(Trans)),0,WACV)   
4012    mainSizer.Add(geoBox,0)
4013    mainSizer.Add((5,5),0)   
4014       
4015    mainSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' S(Q)->F(Q)->G(R) controls: '),0,WACV)
4016    mainSizer.Add((5,5),0)
4017    sqBox = wx.BoxSizer(wx.HORIZONTAL)
4018    sqBox.Add(wx.StaticText(G2frame.dataDisplay,label=' Detector type: '),0,WACV)
4019    choice = ['Image plate','Point detector']
4020    detType = wx.ComboBox(G2frame.dataDisplay,value=data['DetType'],choices=choice,
4021            style=wx.CB_READONLY|wx.CB_DROPDOWN)
4022    detType.Bind(wx.EVT_COMBOBOX, OnDetType)
4023    sqBox.Add(detType,0)
4024    if data['DetType'] == 'Image plate':
4025        sqBox.Add(wx.StaticText(G2frame.dataDisplay,label=' IP transmission coeff.: '),0,WACV)
4026        obliqCoeff = wx.TextCtrl(G2frame.dataDisplay,value='%.3f'%(data['ObliqCoeff']))
4027        obliqCoeff.Bind(wx.EVT_TEXT_ENTER,OnObliqCoeff)       
4028        obliqCoeff.Bind(wx.EVT_KILL_FOCUS,OnObliqCoeff)
4029        sqBox.Add(obliqCoeff,0)
4030    mainSizer.Add(sqBox,0)
4031       
4032    sqBox = wx.BoxSizer(wx.HORIZONTAL)
4033    sqBox.Add(wx.StaticText(G2frame.dataDisplay,label=' Ruland width: '),0,WACV)   
4034    rulandSldr = wx.Slider(parent=G2frame.dataDisplay,style=wx.SL_HORIZONTAL,
4035        value=int(1000*data['Ruland']))
4036    sqBox.Add(rulandSldr,1,wx.EXPAND)
4037    rulandSldr.Bind(wx.EVT_SLIDER, OnRulSlider)
4038    rulandWdt = wx.TextCtrl(G2frame.dataDisplay,value='%.3f'%(data['Ruland']))
4039    rulandWdt.Bind(wx.EVT_TEXT_ENTER,OnRulandWdt)       
4040    rulandWdt.Bind(wx.EVT_KILL_FOCUS,OnRulandWdt)
4041    sqBox.Add(rulandWdt,0,WACV)   
4042    mainSizer.Add(sqBox,0,wx.ALIGN_LEFT|wx.EXPAND)
4043   
4044    sqBox = wx.BoxSizer(wx.HORIZONTAL)
4045    lorch = wx.CheckBox(parent=G2frame.dataDisplay,label='Lorch damping?')
4046    lorch.SetValue(data['Lorch'])
4047    lorch.Bind(wx.EVT_CHECKBOX, OnLorch)
4048    sqBox.Add(lorch,0,WACV)
4049    sqBox.Add(wx.StaticText(G2frame.dataDisplay,label=' Scaling q-range: '),0,WACV)
4050    SQmin = wx.TextCtrl(G2frame.dataDisplay,value='%.1f'%(data['QScaleLim'][0]))
4051    SQmin.Bind(wx.EVT_TEXT_ENTER,OnSQmin)       
4052    SQmin.Bind(wx.EVT_KILL_FOCUS,OnSQmin)   
4053    sqBox.Add(SQmin,0)
4054    sqBox.Add(wx.StaticText(G2frame.dataDisplay,label=' to '),0,WACV)
4055    SQmax = wx.TextCtrl(G2frame.dataDisplay,value='%.1f'%(data['QScaleLim'][1]))
4056    SQmax.Bind(wx.EVT_TEXT_ENTER,OnSQmax)       
4057    SQmax.Bind(wx.EVT_KILL_FOCUS,OnSQmax)
4058    sqBox.Add(SQmax,0)
4059    resetQ = wx.CheckBox(parent=G2frame.dataDisplay,label='Reset?')
4060    sqBox.Add(resetQ,0)
4061    resetQ.Bind(wx.EVT_CHECKBOX, OnResetQ)
4062   
4063    mainSizer.Add(sqBox,0)
4064
4065    mainSizer.Layout()   
4066    G2frame.dataDisplay.SetSizer(mainSizer)
4067    Size = mainSizer.Fit(G2frame.dataFrame)
4068    G2frame.dataDisplay.SetSize(Size)
4069    G2frame.dataFrame.setSizePosLeft(Size)
4070   
Note: See TracBrowser for help on using the repository browser.