source: trunk/GSASIIpwdGUI.py @ 1889

Last change on this file since 1889 was 1889, checked in by toby, 7 years ago

Add fixed background points; animate dragging points and lines; add fixed bkg fit routine (bkg peaks buggy\!)

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