source: trunk/GSASIIpwdGUI.py @ 1547

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

change "Crystal size" to "Domain size"
use lookups for allowed super symmetries for GSAS-II standard space groups as used in the indexing routine.
supersymmetry for trigonal/rhomahedral & hexagonal all complete & checked
supersylmmetry for monoclinic & tetragonal all complete but get errors
orthorhombic not done yet
min Nc/No? set to 2 (at 1 it failed) for indexing

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