source: trunk/GSASIIpwdGUI.py @ 1506

Last change on this file since 1506 was 1506, checked in by vondreele, 7 years ago

break ReadPowderInstprm? into two pieces; OpenPowderInstprm? is new. This will allow using instprm type lines for default instrument parameters instead of old style GSAS ones.
Implement import of superlattice phase and structure factors from JANA2006 files.
Draw superlattice structure factors in 2D & 3D.
Develop GUI for superlattice phase information; atom displacement, Uij, frac & mag waves.
Remove old style mag stuff.
Fix bug in STD powder import .routine for y=0 points
fix bug in getVCov for missing parameter problem.
IsHistogram? InAnyPhase? now returns histogram name instead of True
Single crystal Reflection list now has menu with plot commands

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