source: trunk/GSASIIpwdGUI.py @ 1453

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

get HKLF data type into RefDict?
create a SetDefaultDData routine in GSASII.py
fix copyflags for sc extinction coeff
fix neutron resonant ff for TOF
fix error in making Hessian v-cov matrix - now matches the Jabobian one
put names in the Es, Ep & Eg sc extinction coeff
fix errors in SCExtinction - still problem with derivatives

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