source: trunk/GSASIIpwdGUI.py @ 2136

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

fix indexing problem in 32 bit versions - Skip in ProgressDialog? doesn't work
skip user excluded reflections in HKLF exporters
modify MergeDialog? & more work on LaueUnique?
add 'O' option to 3DHKLF plots to center on origin

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