source: trunk/GSASIIpwdGUI.py @ 1548

Last change on this file since 1548 was 1548, checked in by vondreele, 8 years ago

more super structure stuff - now some in unit cell indexing
now using pulldown ComboBoxes? for supersymmetry choices
continue building tables of supersymmetry codes
use deepcopy for peaks in various places; copy wasn't enough
get seq. peak fit to stop when a refinement goes bad; then allow display of results

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