source: trunk/GSASIIpwdGUI.py @ 1893

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

fix background fitting by interpolation

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