source: trunk/GSASIIpwdGUI.py @ 1559

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

use deepcopy for various copy operations in G2ddataGUI
use complementary colors to background for cell edges
trap superlattice in cubics
more fixes to cell indexing routines from possible use of superlattice
add HStrainVals to G2spc
use it (maybe) in G2strIO, Math
make arguments for GetReflPos? & GetReflPosDeriv? the same (use A not G)
add GetDij? to G2strMath
topas xye file comments start with "'" sometimes

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