source: trunk/GSASIIpwdGUI.py @ 2137

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

fix 3DHKL plot - used Bmat.T should be Bmat; messed up nonorthogonal axes
fix bug in Reflection List

  • Property svn:eol-style set to native
  • Property svn:keywords set to Date Author Revision URL Id
File size: 230.5 KB
Line 
1# -*- coding: utf-8 -*-
2#GSASIIpwdGUI - powder data display routines
3########### SVN repository information ###################
4# $Date: 2016-01-27 17:29:30 +0000 (Wed, 27 Jan 2016) $
5# $Author: vondreele $
6# $Revision: 2137 $
7# $URL: trunk/GSASIIpwdGUI.py $
8# $Id: GSASIIpwdGUI.py 2137 2016-01-27 17:29:30Z 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: 2137 $")
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 = 0.05
3116    if 'UsrReject' in Controls:
3117        dMin = Controls['UsrReject'].get('MinD',0.05)
3118    def OnPlotHKL(event):
3119        '''Plots a layer of reflections
3120        '''
3121        phaseName = G2frame.RefList
3122        if phaseName not in ['Unknown',]:
3123            pId = G2gd.GetPatternTreeItemId(G2frame,G2frame.root,'Phases')
3124            phaseId =  G2gd.GetPatternTreeItemId(G2frame,pId,phaseName)
3125            General = G2frame.PatternTree.GetItemPyData(phaseId)['General']
3126            Super = General.get('Super',0)
3127            SuperVec = General.get('SuperVec',[])
3128        else:
3129            Super = 0
3130            SuperVec = []       
3131        if 'list' in str(type(data)):   #single crystal data is 2 dict in list
3132            refList = data[1]['RefList']
3133        else:                           #powder data is a dict of dicts; each same structure as SC 2nd dict
3134            refList = np.array(data[phaseName]['RefList'])
3135        FoMax = np.max(refList.T[8+Super])
3136        Hmin = np.array([int(np.min(refList.T[0])),int(np.min(refList.T[1])),int(np.min(refList.T[2]))])
3137        Hmax = np.array([int(np.max(refList.T[0])),int(np.max(refList.T[1])),int(np.max(refList.T[2]))])
3138        controls = {'Type' : 'Fo','ifFc' : True,'HKLmax' : Hmax,'HKLmin' : Hmin,
3139            'FoMax' : FoMax,'Zone' : '001','Layer' : 0,'Scale' : 1.0,'Super':Super,'SuperVec':SuperVec}
3140        G2plt.PlotSngl(G2frame,newPlot=True,Data=controls,hklRef=refList,Title=phaseName)
3141       
3142    def OnPlot3DHKL(event):
3143        '''Plots the reflections in 3D
3144        '''
3145        phaseName = G2frame.RefList
3146        if phaseName not in ['Unknown',]:
3147            pId = G2gd.GetPatternTreeItemId(G2frame,G2frame.root,'Phases')
3148            phaseId =  G2gd.GetPatternTreeItemId(G2frame,pId,phaseName)
3149            General = G2frame.PatternTree.GetItemPyData(phaseId)['General']
3150            Super = General.get('Super',0)
3151            SuperVec = General.get('SuperVec',[])
3152        else:
3153            Super = 0
3154            SuperVec = []       
3155        if 'list' in str(type(data)):   #single crystal data is 2 dict in list
3156            refList = data[1]['RefList']
3157        else:                           #powder data is a dict of dicts; each same structure as SC 2nd dict
3158            refList = np.array(data[phaseName]['RefList'])
3159        refList.T[3+Super] = np.where(refList.T[4+Super]<dMin,-refList.T[3+Super],refList.T[3+Super])
3160        FoMax = np.max(refList.T[8+Super])
3161        Hmin = np.array([int(np.min(refList.T[0])),int(np.min(refList.T[1])),int(np.min(refList.T[2]))])
3162        Hmax = np.array([int(np.max(refList.T[0])),int(np.max(refList.T[1])),int(np.max(refList.T[2]))])
3163        Vpoint = np.array([int(np.mean(refList.T[0])),int(np.mean(refList.T[1])),int(np.mean(refList.T[2]))])
3164        controls = {'Type':'Fosq','Iscale':False,'HKLmax':Hmax,'HKLmin':Hmin,'Zone':False,'viewKey':'L',
3165            'FoMax' : FoMax,'Scale' : 1.0,'Drawing':{'viewPoint':[Vpoint,[]],'default':Vpoint[:],
3166            'backColor':[0,0,0],'depthFog':False,'Zclip':10.0,'cameraPos':10.,'Zstep':0.05,'viewUp':[0,1,0],
3167            'Scale':1.0,'oldxy':[],'viewDir':[0,0,1]},'Super':Super,'SuperVec':SuperVec}
3168        G2plt.Plot3DSngl(G2frame,newPlot=True,Data=controls,hklRef=refList,Title=phaseName)
3169       
3170    def MakeReflectionTable(phaseName):
3171        '''Returns a wx.grid table (G2G.Table) containing a list of all reflections
3172        for a phase.       
3173        '''
3174        if phaseName not in ['Unknown',]:
3175            pId = G2gd.GetPatternTreeItemId(G2frame,G2frame.root,'Phases')
3176            phaseId =  G2gd.GetPatternTreeItemId(G2frame,pId,phaseName)
3177            General = G2frame.PatternTree.GetItemPyData(phaseId)['General']
3178            Super = General.get('Super',0)
3179            SuperVec = General.get('SuperVec',[])
3180        else:
3181            Super = 0
3182            SuperVec = []       
3183        rowLabels = []
3184        if HKLF:
3185            refList = data[1]['RefList']
3186            refs = refList
3187        else:
3188            if len(data) > 1:
3189                G2frame.dataFrame.SelectPhase.Enable(True)
3190            try:            #patch for old reflection lists
3191                if not len(data[phaseName]):
3192                    return None
3193                refList = np.array(data[phaseName]['RefList'])
3194                I100 = refList.T[8+Super]*refList.T[11+Super]
3195            except TypeError:
3196                refList = np.array([refl[:11+Super] for refl in data[phaseName]])
3197                I100 = refList.T[8+Super]*np.array([refl[11+Super] for refl in data[phaseName]])
3198            Imax = np.max(I100)
3199            if Imax:
3200                I100 *= 100.0/Imax
3201            if 'C' in Inst['Type'][0]:
3202                refs = np.vstack((refList.T[:15+Super],I100)).T
3203            elif 'T' in Inst['Type'][0]:
3204                refs = np.vstack((refList.T[:18+Super],I100)).T
3205            G2frame.HKL = np.vstack((refList.T[:6+Super])).T    #build for plots
3206        rowLabels = [str(i) for i in range(len(refs))]
3207        Types = (4+Super)*[wg.GRID_VALUE_LONG,]+4*[wg.GRID_VALUE_FLOAT+':10,4',]+ \
3208            2*[wg.GRID_VALUE_FLOAT+':10,2',]+[wg.GRID_VALUE_FLOAT+':10,3',]+ \
3209            [wg.GRID_VALUE_FLOAT+':10,3',]
3210        if HKLF:
3211            colLabels = ['H','K','L','twin','d','Fosq','sig','Fcsq','FoTsq','FcTsq','phase','ExtC',]
3212            if 'T' in Inst['Type'][0]:
3213                colLabels = ['H','K','L','twin','d','Fosq','sig','Fcsq','FoTsq','FcTsq','phase','ExtC','wave','tbar']
3214                Types += 2*[wg.GRID_VALUE_FLOAT+':10,3',]
3215            if Super:
3216                colLabels.insert(3,'M')
3217        else:
3218            if 'C' in Inst['Type'][0]:
3219                colLabels = ['H','K','L','mul','d','pos','sig','gam','Fosq','Fcsq','phase','Icorr','Prfo','Trans','ExtP','I100']
3220                Types += 4*[wg.GRID_VALUE_FLOAT+':10,3',]
3221            elif 'T' in Inst['Type'][0]:
3222                colLabels = ['H','K','L','mul','d','pos','sig','gam','Fosq','Fcsq','phase','Icorr','alp','bet','wave','Prfo','Abs','Ext','I100']
3223                Types += 7*[wg.GRID_VALUE_FLOAT+':10,3',]
3224            if Super:
3225                colLabels.insert(3,'M')
3226        refs.T[3+Super] = np.where(refs.T[4+Super]<dMin,-refs.T[3+Super],refs.T[3+Super])
3227        return G2G.Table(refs,rowLabels=rowLabels,colLabels=colLabels,types=Types)
3228
3229    def ShowReflTable(phaseName):
3230        '''Posts a table of reflections for a phase, creating the table
3231        if needed using MakeReflectionTable
3232        '''
3233        def setBackgroundColors(im,it):
3234            for r in range(G2frame.refTable[phaseName].GetNumberRows()):
3235                if HKLF:
3236                    if float(G2frame.refTable[phaseName].GetCellValue(r,3+im)) <= 0.:
3237                        G2frame.refTable[phaseName].SetCellBackgroundColour(r,3+im,wx.RED)
3238                    Fosq = float(G2frame.refTable[phaseName].GetCellValue(r,5+im))
3239                    Fcsq = float(G2frame.refTable[phaseName].GetCellValue(r,7+im))
3240                    sig = float(G2frame.refTable[phaseName].GetCellValue(r,6+im))
3241                    rat = abs(Fosq-Fcsq)/sig
3242                    if  rat > 10.:
3243                        G2frame.refTable[phaseName].SetCellBackgroundColour(r,7+im,wx.RED)
3244                    elif rat > 3.0:
3245                        G2frame.refTable[phaseName].SetCellBackgroundColour(r,7+im,wx.Colour(255,255,0))
3246#                    else:
3247#                        G2frame.refTable[phaseName].SetCellBackgroundColour(r,7+im,wx.WHITE)
3248                else:   #PWDR
3249                    if float(G2frame.refTable[phaseName].GetCellValue(r,12+im+itof)) < 0.:
3250                        G2frame.refTable[phaseName].SetCellBackgroundColour(r,12+im+itof,wx.RED)
3251                    if float(G2frame.refTable[phaseName].GetCellValue(r,3+im)) < 0:
3252                        G2frame.refTable[phaseName].SetCellBackgroundColour(r,8+im,wx.RED)
3253                       
3254                                                 
3255        G2frame.RefList = phaseName
3256        G2frame.dataFrame.SetLabel('Reflection List for '+phaseName)
3257        if HKLF:
3258            Status.SetStatusText('abs(DF)/sig > 10 red; > 3 yellow; twin < 0 (user rejected) red; twin=0 (sp. gp. absent) red')
3259        else:
3260            Status.SetStatusText('Prfo < 0. in red; if excluded Fosq in red & mul < 0')
3261        itof = 0
3262        if HKLF:
3263            im = data[1].get('Super',0)
3264        else:
3265            if 'T' in data[phaseName].get('Type',''):
3266                itof = 3
3267            im = data[phaseName].get('Super',0)
3268        # has this table already been displayed?
3269        if G2frame.refTable[phaseName].GetTable() is None:
3270            PeakTable = MakeReflectionTable(phaseName)
3271            G2frame.refTable[phaseName].SetTable(PeakTable, True)
3272            G2frame.refTable[phaseName].EnableEditing(False)
3273            G2frame.refTable[phaseName].SetMargins(0,0)
3274            G2frame.refTable[phaseName].AutoSizeColumns(False)
3275            setBackgroundColors(im,itof)
3276        # raise the tab (needed for 1st use and from OnSelectPhase)
3277        for PageNum in range(G2frame.dataDisplay.GetPageCount()):
3278            if phaseName == G2frame.dataDisplay.GetPageText(PageNum):
3279                G2frame.dataDisplay.SetSelection(PageNum)
3280                break
3281        else:
3282            print phaseName
3283            print phases
3284            raise Exception("how did we not find a phase name?")
3285       
3286    def OnPageChanged(event):
3287        '''Respond to a press on a phase tab by displaying the reflections. This
3288        routine is needed because the reflection table may not have been created yet.
3289        '''
3290        page = event.GetSelection()
3291        phaseName = G2frame.dataDisplay.GetPageText(page)
3292        ShowReflTable(phaseName)
3293
3294    def OnSelectPhase(event):
3295        '''For PWDR, selects a phase with a selection box. Called from menu.
3296        '''
3297        if len(phases) < 2: return
3298        dlg = wx.SingleChoiceDialog(G2frame,'Select','Phase',phases)
3299        try:
3300            if dlg.ShowModal() == wx.ID_OK:
3301                sel = dlg.GetSelection()
3302                ShowReflTable(phases[sel])
3303        finally:
3304            dlg.Destroy()
3305           
3306    if not data:
3307        print 'No phases, no reflections'
3308        return
3309    if HKLF:
3310        G2frame.RefList = 1
3311        phaseName = IsHistogramInAnyPhase(G2frame,Name)
3312        if not phaseName:
3313            phaseName = 'Unknown'
3314        phases = [phaseName]
3315    else:
3316        phaseName = G2frame.RefList
3317        phases = data.keys()
3318    if G2frame.dataDisplay:
3319        G2frame.dataFrame.Clear()
3320    Inst = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,G2frame.PatternId, 'Instrument Parameters'))[0]
3321    if HKLF:
3322        G2gd.SetDataMenuBar(G2frame)
3323        G2gd.SetDataMenuBar(G2frame,G2frame.dataFrame.ReflMenu)
3324        if not G2frame.dataFrame.GetStatusBar():
3325            Status = G2frame.dataFrame.CreateStatusBar()   
3326        G2frame.Bind(wx.EVT_MENU, OnPlotHKL, id=G2gd.wxID_PWDHKLPLOT)
3327        G2frame.Bind(wx.EVT_MENU, OnPlot3DHKL, id=G2gd.wxID_PWD3DHKLPLOT)
3328        G2frame.dataFrame.SelectPhase.Enable(False)
3329    else:
3330        G2gd.SetDataMenuBar(G2frame,G2frame.dataFrame.ReflMenu)
3331        if not G2frame.dataFrame.GetStatusBar():
3332            Status = G2frame.dataFrame.CreateStatusBar()   
3333        G2frame.Bind(wx.EVT_MENU, OnSelectPhase, id=G2gd.wxID_SELECTPHASE)
3334        G2frame.Bind(wx.EVT_MENU, OnPlotHKL, id=G2gd.wxID_PWDHKLPLOT)
3335        G2frame.Bind(wx.EVT_MENU, OnPlot3DHKL, id=G2gd.wxID_PWD3DHKLPLOT)
3336        G2frame.dataFrame.SelectPhase.Enable(False)
3337           
3338    G2frame.dataDisplay = G2G.GSNoteBook(parent=G2frame.dataFrame,size=G2frame.dataFrame.GetClientSize())
3339    G2frame.refTable = {}
3340    for tabnum,phase in enumerate(phases):
3341        G2frame.refTable[phase] = G2G.GSGrid(parent=G2frame.dataDisplay)
3342        G2frame.dataDisplay.AddPage(G2frame.refTable[phase],phase)
3343#    if phaseName not in G2frame.refTable:
3344#        print phaseName
3345#        print phases
3346#        raise Exception("how did we get a invalid phase name?")   
3347    ShowReflTable(phaseName)
3348#    G2frame.refTable[phaseName].Fit()   #slow!!
3349#    size = G2frame.refTable[phaseName].GetSize()
3350#    G2frame.dataFrame.setSizePosLeft([size[0]+32,350])
3351    G2frame.dataFrame.setSizePosLeft([550,350])
3352    G2frame.dataDisplay.Bind(wx.aui.EVT_AUINOTEBOOK_PAGE_CHANGED, OnPageChanged)
3353   
3354################################################################################
3355#####  SASD Substances
3356################################################################################
3357           
3358def UpdateSubstanceGrid(G2frame,data):
3359    '''respond to selection of SASD Substance data tree item.
3360    '''
3361    import Substances as substFile
3362   
3363    def OnLoadSubstance(event):
3364        names = substFile.Substances.keys()
3365        names.sort()
3366        dlg = wx.SingleChoiceDialog(G2frame, 'Which substance?', 'Select substance', names, wx.CHOICEDLG_STYLE)
3367        try:
3368            if dlg.ShowModal() == wx.ID_OK:
3369                name = names[dlg.GetSelection()]
3370            else:
3371                return
3372        finally:
3373            dlg.Destroy()
3374        data['Substances'][name] = {'Elements':{},'Volume':1.0,'Density':1.0,
3375            'Scatt density':0.0,'XAnom density':0.0,'XAbsorption':0.0}
3376        subst = substFile.Substances[name]
3377        ElList = subst['Elements'].keys()
3378        for El in ElList:
3379            Info = G2elem.GetAtomInfo(El.strip().capitalize())
3380            Info.update(subst['Elements'][El])
3381            data['Substances'][name]['Elements'][El] = Info
3382            if 'Volume' in subst:
3383                data['Substances'][name]['Volume'] = subst['Volume']
3384                data['Substances'][name]['Density'] = \
3385                    G2mth.Vol2Den(data['Substances'][name]['Elements'],data['Substances'][name]['Volume'])
3386            elif 'Density' in subst:
3387                data['Substances'][name]['Density'] = subst['Density']
3388                data['Substances'][name]['Volume'] = \
3389                    G2mth.Den2Vol(data['Substances'][name]['Elements'],data['Substances'][name]['Density'])
3390            else:
3391                data['Substances'][name]['Volume'] = G2mth.El2EstVol(data['Substances'][name]['Elements'])
3392                data['Substances'][name]['Density'] = \
3393                    G2mth.Vol2Den(data['Substances'][name]['Elements'],data['Substances'][name]['Volume'])
3394            data['Substances'][name]['Scatt density'] = \
3395                G2mth.XScattDen(data['Substances'][name]['Elements'],data['Substances'][name]['Volume'])[0]
3396            contrst,absorb = G2mth.XScattDen(data['Substances'][name]['Elements'],data['Substances'][name]['Volume'],wave)         
3397            data['Substances'][name]['XAnom density'] = contrst
3398            data['Substances'][name]['XAbsorption'] = absorb
3399                         
3400        UpdateSubstanceGrid(G2frame,data)
3401       
3402    def OnCopySubstance(event):
3403        hst = G2frame.PatternTree.GetItemText(G2frame.PatternId)
3404        histList = GetHistsLikeSelected(G2frame)
3405        if not histList:
3406            G2frame.ErrorDialog('No match','No histograms match '+hst,G2frame.dataFrame)
3407            return
3408        copyList = []
3409        dlg = G2G.G2MultiChoiceDialog(
3410            G2frame.dataFrame, 
3411            'Copy substances from\n'+hst[5:]+' to...',
3412            'Copy substances', histList)
3413        try:
3414            if dlg.ShowModal() == wx.ID_OK:
3415                for i in dlg.GetSelections(): 
3416                    copyList.append(histList[i])
3417        finally:
3418            dlg.Destroy()       
3419        for item in copyList:
3420            Id = G2gd.GetPatternTreeItemId(G2frame,G2frame.root,item)
3421            G2frame.PatternTree.SetItemPyData(G2gd.GetPatternTreeItemId(G2frame,Id,'Substances'),
3422                copy.copy(data))
3423   
3424    def OnAddSubstance(event):
3425        dlg = wx.TextEntryDialog(None,'Enter a name for this substance','Substance Name Entry','New substance',
3426            style=wx.OK)
3427        if dlg.ShowModal() == wx.ID_OK:
3428            Name = dlg.GetValue()
3429            data['Substances'][Name] = {'Elements':{},'Volume':1.0,'Density':1.0,
3430                'Scatt density':0.0,'XAnom density':0.,'XAbsorption':0.}
3431        dlg.Destroy()
3432        AddElement(Name)
3433        UpdateSubstanceGrid(G2frame,data)
3434       
3435    def OnDeleteSubstance(event):
3436        TextList = []
3437        for name in data['Substances']:
3438            if name != 'vacuum':
3439                TextList += [name,]
3440        if not TextList:
3441            return
3442        dlg = wx.SingleChoiceDialog(G2frame, 'Which substance?', 'Select substance to delete', TextList, wx.CHOICEDLG_STYLE)
3443        try:
3444            if dlg.ShowModal() == wx.ID_OK:
3445                name = TextList[dlg.GetSelection()]
3446            else:
3447                return
3448        finally:
3449            dlg.Destroy()
3450        del(data['Substances'][name])
3451        UpdateSubstanceGrid(G2frame,data)       
3452               
3453    def OnAddElement(event):       
3454        TextList = []
3455        for name in data['Substances']:
3456            if name != 'vacuum':
3457                TextList += [name,]
3458        if not TextList:
3459            return
3460        dlg = wx.SingleChoiceDialog(G2frame, 'Which substance?', 'Select substance', TextList, wx.CHOICEDLG_STYLE)
3461        try:
3462            if dlg.ShowModal() == wx.ID_OK:
3463                name = TextList[dlg.GetSelection()]
3464            else:
3465                return
3466        finally:
3467            dlg.Destroy()
3468        AddElement(name)
3469        UpdateSubstanceGrid(G2frame,data)
3470       
3471    def AddElement(name):
3472        ElList = data['Substances'][name]['Elements'].keys()
3473        dlg = G2elemGUI.PickElements(G2frame,ElList)
3474        if dlg.ShowModal() == wx.ID_OK:
3475            for El in dlg.Elem:
3476                El = El.strip().capitalize()
3477                Info = G2elem.GetAtomInfo(El)
3478                Info.update({'Num':1})
3479                data['Substances'][name]['Elements'][El] = Info
3480                data['Substances'][name]['Volume'] = G2mth.El2EstVol(data['Substances'][name]['Elements'])
3481                data['Substances'][name]['Density'] = \
3482                    G2mth.Vol2Den(data['Substances'][name]['Elements'],data['Substances'][name]['Volume'])
3483                data['Substances'][name]['Scatt density'] = \
3484                    G2mth.XScattDen(data['Substances'][name]['Elements'],data['Substances'][name]['Volume'])[0]
3485                contrst,absorb = G2mth.XScattDen(data['Substances'][name]['Elements'],data['Substances'][name]['Volume'],wave)         
3486                data['Substances'][name]['XAnom density'] = contrst
3487                data['Substances'][name]['XAbsorption'] = absorb
3488        dlg.Destroy()
3489       
3490    def OnDeleteElement(event):
3491        TextList = []
3492        for name in data['Substances']:
3493            if name != 'vacuum':
3494                TextList += [name,]
3495        if not TextList:
3496            return
3497        dlg = wx.SingleChoiceDialog(G2frame, 'Which substance?', 'Select substance', TextList, wx.CHOICEDLG_STYLE)
3498        try:
3499            if dlg.ShowModal() == wx.ID_OK:
3500                name = TextList[dlg.GetSelection()]
3501            else:
3502                return
3503        finally:
3504            dlg.Destroy()
3505        ElList = data['Substances'][name]['Elements'].keys()
3506        if len(ElList):
3507            DE = G2elemGUI.DeleteElement(G2frame,ElList)
3508            if DE.ShowModal() == wx.ID_OK:
3509                El = DE.GetDeleteElement().strip().upper()
3510                del(data['Substances'][name]['Elements'][El])
3511                data['Substances'][name]['Volume'] = G2mth.El2EstVol(data['Substances'][name]['Elements'])
3512                data['Substances'][name]['Density'] = \
3513                    G2mth.Vol2Den(data['Substances'][name]['Elements'],data['Substances'][name]['Volume'])
3514                data['Substances'][name]['Scatt density'] = \
3515                    G2mth.XScattDen(data['Substances'][name]['Elements'],data['Substances'][name]['Volume'])[0]
3516                contrst,absorb = G2mth.XScattDen(data['Substances'][name]['Elements'],data['Substances'][name]['Volume'],wave)         
3517                data['Substances'][name]['XAnom density'] = contrst
3518                data['Substances'][name]['XAbsorption'] = absorb
3519        UpdateSubstanceGrid(G2frame,data)
3520               
3521    def SubstSizer():
3522       
3523        def OnValueChange(event):
3524            Obj = event.GetEventObject()
3525            if len(Indx[Obj.GetId()]) == 3:
3526                name,El,keyId = Indx[Obj.GetId()]
3527                try:
3528                    value = max(0,float(Obj.GetValue()))
3529                except ValueError:
3530                    value = 0
3531                    Obj.SetValue('%.2f'%(value))
3532                data['Substances'][name]['Elements'][El][keyId] = value
3533                data['Substances'][name]['Volume'] = G2mth.El2EstVol(data['Substances'][name]['Elements'])
3534                data['Substances'][name]['Density'] = \
3535                    G2mth.Vol2Den(data['Substances'][name]['Elements'],data['Substances'][name]['Volume'])
3536            else:
3537                name,keyId = Indx[Obj.GetId()]
3538                try:
3539                    value = max(0,float(Obj.GetValue()))
3540                except ValueError:
3541                    value = 1.0
3542                data['Substances'][name][keyId] = value
3543                if keyId in 'Volume':
3544                    data['Substances'][name]['Density'] = \
3545                        G2mth.Vol2Den(data['Substances'][name]['Elements'],value)
3546                elif keyId in 'Density':
3547                    data['Substances'][name]['Volume'] = \
3548                        G2mth.Den2Vol(data['Substances'][name]['Elements'],value)
3549            data['Substances'][name]['Scatt density'] = \
3550                G2mth.XScattDen(data['Substances'][name]['Elements'],data['Substances'][name]['Volume'])[0]
3551            contrst,absorb = G2mth.XScattDen(data['Substances'][name]['Elements'],data['Substances'][name]['Volume'],wave)         
3552            data['Substances'][name]['XAnom density'] = contrst
3553            data['Substances'][name]['XAbsorption'] = absorb
3554            wx.CallAfter(UpdateSubstanceGrid,G2frame,data)
3555       
3556        Indx = {}
3557        substSizer = wx.BoxSizer(wx.VERTICAL)
3558        substSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' Substance list: wavelength: %.5fA'%(wave)),
3559            0,WACV)
3560        for name in data['Substances']:
3561            G2G.HorizontalLine(substSizer,G2frame.dataDisplay)   
3562            substSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' Data for '+name+':'),
3563                0,WACV)
3564            if name == 'vacuum':
3565                substSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label='        Not applicable'),
3566                    0,WACV)
3567            else:   
3568                elSizer = wx.FlexGridSizer(0,6,5,5)
3569                Substance = data['Substances'][name]
3570                Elems = Substance['Elements']
3571                for El in Elems:    #do elements as pull downs for isotopes for neutrons
3572                    elSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' '+El+': '),
3573                        0,WACV)
3574                    num = wx.TextCtrl(G2frame.dataDisplay,value='%.2f'%(Elems[El]['Num']),style=wx.TE_PROCESS_ENTER)
3575                    Indx[num.GetId()] = [name,El,'Num']
3576                    num.Bind(wx.EVT_TEXT_ENTER,OnValueChange)       
3577                    num.Bind(wx.EVT_KILL_FOCUS,OnValueChange)
3578                    elSizer.Add(num,0,WACV)
3579                substSizer.Add(elSizer,0)
3580                vdsSizer = wx.FlexGridSizer(0,4,5,5)
3581                vdsSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' Volume: '),
3582                    0,WACV)
3583                vol = wx.TextCtrl(G2frame.dataDisplay,value='%.3f'%(Substance['Volume']),style=wx.TE_PROCESS_ENTER)
3584                Indx[vol.GetId()] = [name,'Volume']
3585                vol.Bind(wx.EVT_TEXT_ENTER,OnValueChange)       
3586                vol.Bind(wx.EVT_KILL_FOCUS,OnValueChange)
3587                vdsSizer.Add(vol,0,WACV)               
3588                vdsSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' Density: '),
3589                    0,WACV)
3590                den = wx.TextCtrl(G2frame.dataDisplay,value='%.3f'%(Substance['Density']),style=wx.TE_PROCESS_ENTER)
3591                Indx[den.GetId()] = [name,'Density']
3592                den.Bind(wx.EVT_TEXT_ENTER,OnValueChange)       
3593                den.Bind(wx.EVT_KILL_FOCUS,OnValueChange)
3594                vdsSizer.Add(den,0,WACV)
3595                substSizer.Add(vdsSizer,0)
3596                substSizer.Add(wx.StaticText(G2frame.dataDisplay,
3597                    label=' Scattering density  : %.2f *10%scm%s'%(Substance['Scatt density'],Pwr10,Pwrm2)),
3598                    0,WACV)               
3599                substSizer.Add(wx.StaticText(G2frame.dataDisplay,       #allow neutrons here into NAnom density & NAbsorption
3600                    label=' Anomalous density : %.2f *10%scm%s'%(Substance['XAnom density'],Pwr10,Pwrm2)),
3601                    0,WACV)               
3602                substSizer.Add(wx.StaticText(G2frame.dataDisplay,
3603                    label=' X-ray absorption   : %.2f cm%s'%(Substance['XAbsorption'],Pwrm1)),
3604                    0,WACV)               
3605        return substSizer
3606           
3607    Inst = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,G2frame.PatternId, 'Instrument Parameters'))[0]
3608    wave = G2mth.getWave(Inst)
3609    if G2frame.dataDisplay:
3610        G2frame.dataFrame.DestroyChildren()  # is this a ScrolledWindow? If so, bad!
3611    G2gd.SetDataMenuBar(G2frame,G2frame.dataFrame.SubstanceMenu)
3612    if not G2frame.dataFrame.GetStatusBar():
3613        Status = G2frame.dataFrame.CreateStatusBar()
3614    G2frame.dataDisplay = wxscroll.ScrolledPanel(G2frame.dataFrame)
3615    G2frame.dataFrame.SetLabel('Substances')
3616    G2frame.dataFrame.Bind(wx.EVT_MENU, OnLoadSubstance, id=G2gd.wxID_LOADSUBSTANCE)   
3617    G2frame.dataFrame.Bind(wx.EVT_MENU, OnAddSubstance, id=G2gd.wxID_ADDSUBSTANCE)
3618    G2frame.dataFrame.Bind(wx.EVT_MENU, OnCopySubstance, id=G2gd.wxID_COPYSUBSTANCE)
3619    G2frame.dataFrame.Bind(wx.EVT_MENU, OnDeleteSubstance, id=G2gd.wxID_DELETESUBSTANCE)   
3620    G2frame.dataFrame.Bind(wx.EVT_MENU, OnAddElement, id=G2gd.wxID_ELEMENTADD)
3621    G2frame.dataFrame.Bind(wx.EVT_MENU, OnDeleteElement, id=G2gd.wxID_ELEMENTDELETE)
3622    mainSizer = wx.BoxSizer(wx.VERTICAL)
3623    mainSizer.Add(SubstSizer(),0)
3624
3625    mainSizer.Layout()   
3626    G2frame.dataDisplay.SetSizer(mainSizer)
3627    G2frame.dataDisplay.SetAutoLayout(1)
3628    G2frame.dataDisplay.SetupScrolling()
3629    Size = mainSizer.Fit(G2frame.dataFrame)
3630    Size[0] += 25
3631    G2frame.dataDisplay.SetSize(Size)
3632    G2frame.dataFrame.setSizePosLeft(Size)   
3633       
3634################################################################################
3635#####  SASD Models
3636################################################################################           
3637       
3638def UpdateModelsGrid(G2frame,data):
3639    '''respond to selection of SASD Models data tree item.
3640    '''
3641    #patches
3642    if 'Current' not in data:
3643        data['Current'] = 'Size dist.'
3644    if 'logBins' not in data['Size']:
3645        data['Size']['logBins'] = True
3646    if 'MinMaxDiam' in data['Size']:
3647        data['Size']['MinDiam'] = 50.
3648        data['Size']['MaxDiam'] = 10000.
3649        del data['Size']['MinMaxDiam']
3650    if isinstance(data['Size']['MaxEnt']['Sky'],float):
3651        data['Size']['MaxEnt']['Sky'] = -3
3652    if 'Power' not in data['Size']['IPG']:
3653        data['Size']['IPG']['Power'] = -1
3654    if 'Matrix' not in data['Particle']:
3655        data['Particle']['Matrix'] = {'Name':'vacuum','VolFrac':[0.0,False]}
3656    if 'BackFile' not in data:
3657        data['BackFile'] = ''
3658    #end patches
3659   
3660    def RefreshPlots(newPlot=False):
3661        PlotText = G2frame.G2plotNB.nb.GetPageText(G2frame.G2plotNB.nb.GetSelection())
3662        if 'Powder' in PlotText:
3663            G2plt.PlotPatterns(G2frame,plotType='SASD',newPlot=newPlot)
3664        elif 'Size' in PlotText:
3665            G2plt.PlotSASDSizeDist(G2frame)
3666               
3667    def OnAddModel(event):
3668        if data['Current'] == 'Particle fit':
3669            material = 'vacuum'
3670            if len(data['Particle']['Levels']):
3671                material = data['Particle']['Levels'][-1]['Controls']['Material']
3672            data['Particle']['Levels'].append({
3673                'Controls':{'FormFact':'Sphere','DistType':'LogNormal','Material':material,
3674                    'FFargs':{},'SFargs':{},'NumPoints':50,'Cutoff':0.01,'Contrast':0.0,
3675                    'SlitSmear':[0.0,False],'StrFact':'Dilute'},    #last 2 not used - future?
3676                'LogNormal':{'Volume':[0.05,False],'Mean':[1000.,False],'StdDev':[0.5,False],'MinSize':[10.,False],},
3677                'Gaussian':{'Volume':[0.05,False],'Mean':[1000.,False],'StdDev':[300.,False],},
3678                'LSW':{'Volume':[0.05,False],'Mean':[1000.0,False],},
3679                'Schulz-Zimm':{'Volume':[0.05,False],'Mean':[1000.,False],'StdDev':[300.,False],},
3680                'Unified':{'G':[1.e3,False],'Rg':[100,False],'B':[1.e-5,False],'P':[4,False],'Cutoff':[1e-5,False],},
3681                'Porod':{'B':[1.e-4,False],'P':[4,False],'Cutoff':[1e-5,False],},
3682                'Monodisperse':{'Volume':[0.05,False],'Radius':[100,False],},   #OK for spheres
3683                'Bragg':{'PkInt':[100,False],'PkPos':[0.2,False],
3684                    'PkSig':[10,False],'PkGam':[10,False],},        #reasonable 31A peak
3685                })
3686            G2sasd.ModelFxn(Profile,ProfDict,Limits,Sample,data)
3687            RefreshPlots(True)
3688                   
3689        wx.CallAfter(UpdateModelsGrid,G2frame,data)
3690       
3691    def OnCopyModel(event):
3692        hst = G2frame.PatternTree.GetItemText(G2frame.PatternId)
3693        histList = GetHistsLikeSelected(G2frame)
3694        if not histList:
3695            G2frame.ErrorDialog('No match','No histograms match '+hst,G2frame.dataFrame)
3696            return
3697        copyList = []
3698        dlg = G2G.G2MultiChoiceDialog(
3699            G2frame.dataFrame, 
3700            'Copy models from\n'+hst[5:]+' to...',
3701            'Copy models', histList)
3702        try:
3703            if dlg.ShowModal() == wx.ID_OK:
3704                for i in dlg.GetSelections(): 
3705                    copyList.append(histList[i])
3706        finally:
3707            dlg.Destroy()       
3708        for item in copyList:
3709            Id = G2gd.GetPatternTreeItemId(G2frame,G2frame.root,item)
3710            newdata = copy.deepcopy(data)
3711            G2frame.PatternTree.SetItemPyData(G2gd.GetPatternTreeItemId(G2frame,Id,'Models'),newdata)
3712            if newdata['BackFile']:
3713                Profile = G2frame.PatternTree.GetItemPyData(Id)[1]
3714                BackId = G2gd.GetPatternTreeItemId(G2frame,G2frame.root,newdata['BackFile'])
3715                BackSample = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,BackId, 'Sample Parameters'))
3716                Profile[5] = BackSample['Scale'][0]*G2frame.PatternTree.GetItemPyData(BackId)[1][1]
3717        RefreshPlots(True)
3718               
3719    def OnCopyFlags(event):
3720        thisModel = copy.deepcopy(data)
3721        hst = G2frame.PatternTree.GetItemText(G2frame.PatternId)
3722        histList = GetHistsLikeSelected(G2frame)
3723        if not histList:
3724            G2frame.ErrorDialog('No match','No histograms match '+hst,G2frame.dataFrame)
3725            return
3726        dlg = G2G.G2MultiChoiceDialog(
3727            G2frame.dataFrame, 
3728            'Copy sample ref. flags from\n'+str(hst[5:])+' to...',
3729            'Copy sample flags', histList)
3730        distChoice = ['LogNormal','Gaussian','LSW','Schulz-Zimm','Bragg','Unified',
3731            'Porod','Monodisperse',]
3732        parmOrder = ['Volume','Radius','Mean','StdDev','G','Rg','B','P',
3733            'Cutoff','PkInt','PkPos','PkSig','PkGam','VolFr','Dist',]
3734        try:
3735            if dlg.ShowModal() == wx.ID_OK:
3736                result = dlg.GetSelections()
3737                for i in result: 
3738                    item = histList[i]
3739                    Id = G2gd.GetPatternTreeItemId(G2frame,G2frame.root,item)
3740                    newModel = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,Id,'Models'))
3741                    newModel['Back'][1] = copy.copy(thisModel['Back'][1])
3742                    for ilev,level in enumerate(newModel['Particle']['Levels']):
3743                        for form in level:
3744                            if form in distChoice:
3745                                thisForm = thisModel['Particle']['Levels'][ilev][form]                               
3746                                for item in parmOrder:
3747                                    if item in thisForm:
3748                                       level[form][item][1] = copy.copy(thisForm[item][1])
3749                            elif form == 'Controls':
3750                                thisForm = thisModel['Particle']['Levels'][ilev][form]['SFargs']
3751                                for item in parmOrder:
3752                                    if item in thisForm:
3753                                        level[form]['SFargs'][item][1] = copy.copy(thisForm[item][1])
3754        finally:
3755            dlg.Destroy()
3756               
3757    def OnFitModelAll(event):
3758        choices = G2gd.GetPatternTreeDataNames(G2frame,['SASD',])
3759        sel = []
3760        dlg = G2G.G2MultiChoiceDialog(G2frame.dataFrame, 'Sequential SASD refinement',
3761             'Select dataset to include',choices)
3762        dlg.SetSelections(sel)
3763        names = []
3764        if dlg.ShowModal() == wx.ID_OK:
3765            for sel in dlg.GetSelections():
3766                names.append(choices[sel])
3767        dlg.Destroy()
3768        SeqResult = {'histNames':names}
3769        Reverse = False
3770        CopyForward = False
3771        choice = ['Reverse sequence','Copy from prev.']
3772        dlg = wx.MultiChoiceDialog(G2frame.dataFrame,'Sequential controls','Select controls',choice)
3773        if dlg.ShowModal() == wx.ID_OK:
3774            for sel in dlg.GetSelections():
3775                if sel:
3776                    CopyForward = True
3777                else:
3778                    Reverse = True
3779        dlg.Destroy()
3780        dlg = wx.ProgressDialog('SASD Sequential fit','Data set name = '+names[0],len(names), 
3781            style = wx.PD_ELAPSED_TIME|wx.PD_AUTO_HIDE|wx.PD_REMAINING_TIME|wx.PD_CAN_ABORT)
3782        wx.BeginBusyCursor()
3783        if Reverse:
3784            names.reverse()
3785        try:
3786            for i,name in enumerate(names):
3787                print ' Sequential fit for ',name
3788                GoOn = dlg.Update(i,newmsg='Data set name = '+name)[0]
3789                if not GoOn:
3790                    break
3791                Id =  G2gd.GetPatternTreeItemId(G2frame,G2frame.root,name)
3792                if i and CopyForward:
3793                    G2frame.PatternTree.SetItemPyData(G2gd.GetPatternTreeItemId(G2frame,Id, 'Models'),JModel)
3794                IProfDict,IProfile = G2frame.PatternTree.GetItemPyData(Id)[:2]
3795                IModel = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,Id, 'Models'))
3796                ISample = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,Id, 'Sample Parameters'))
3797                ILimits = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,Id, 'Limits'))
3798                IfOK,result,varyList,sig,Rvals,covMatrix,parmDict,Msg = G2sasd.ModelFit(IProfile,IProfDict,ILimits,ISample,IModel)
3799                JModel = copy.deepcopy(IModel)
3800                if not IfOK:
3801                    G2frame.ErrorDialog('Failed sequential refinement for data '+name,
3802                        ' Msg: '+Msg+'\nYou need to rethink your selection of parameters\n'+    \
3803                        ' Model restored to previous version for'+name)
3804                    SeqResult['histNames'] = names[:i]
3805                    dlg.Destroy()
3806                    break
3807                else:
3808                    G2frame.PatternTree.SetItemPyData(G2gd.GetPatternTreeItemId(G2frame,Id, 'Models'),copy.deepcopy(IModel))
3809               
3810                G2sasd.ModelFxn(IProfile,IProfDict,ILimits,ISample,IModel)
3811                SeqResult[name] = {'variables':result[0],'varyList':varyList,'sig':sig,'Rvals':Rvals,
3812                    'covMatrix':covMatrix,'title':name,'parmDict':parmDict}
3813            else:
3814                dlg.Destroy()
3815                print ' ***** Small angle sequential refinement successful *****'
3816        finally:
3817            wx.EndBusyCursor()   
3818        Id =  G2gd.GetPatternTreeItemId(G2frame,G2frame.root,'Sequential results')
3819        if Id:
3820            G2frame.PatternTree.SetItemPyData(Id,SeqResult)
3821        else:
3822            Id = G2frame.PatternTree.AppendItem(parent=G2frame.root,text='Sequential results')
3823            G2frame.PatternTree.SetItemPyData(Id,SeqResult)
3824        G2frame.PatternTree.SelectItem(Id)
3825       
3826    def OnFitModel(event):
3827        if data['Current'] == 'Size dist.':
3828            if not any(Sample['Contrast']):
3829                G2frame.ErrorDialog('No contrast; your sample is a vacuum!',
3830                    'You need to define a scattering substance!\n'+    \
3831                    ' Do Substances and then Sample parameters')
3832                return
3833            G2sasd.SizeDistribution(Profile,ProfDict,Limits,Sample,data)
3834            G2plt.PlotSASDSizeDist(G2frame)
3835            RefreshPlots(True)
3836           
3837        elif data['Current'] == 'Particle fit':
3838            SaveState()
3839            Results = G2sasd.ModelFit(Profile,ProfDict,Limits,Sample,data)
3840            if not Results[0]:
3841                    G2frame.ErrorDialog('Failed refinement',
3842                        ' Msg: '+Results[-1]+'\nYou need to rethink your selection of parameters\n'+    \
3843                        ' Model restored to previous version')
3844            G2sasd.ModelFxn(Profile,ProfDict,Limits,Sample,data)
3845            RefreshPlots(True)
3846            wx.CallAfter(UpdateModelsGrid,G2frame,data)
3847           
3848    def OnUnDo(event):
3849        DoUnDo()
3850        data = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,
3851            G2frame.PatternId,'Models'))
3852        G2frame.dataFrame.SasdUndo.Enable(False)
3853        UpdateModelsGrid(G2frame,data)
3854        G2sasd.ModelFxn(Profile,ProfDict,Limits,Sample,data)
3855        RefreshPlots(True)
3856
3857    def DoUnDo():
3858        print 'Undo last refinement'
3859        file = open(G2frame.undosasd,'rb')
3860        PatternId = G2frame.PatternId
3861        G2frame.PatternTree.SetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId, 'Models'),cPickle.load(file))
3862        print ' Models recovered'
3863        file.close()
3864       
3865    def SaveState():
3866        G2frame.undosasd = os.path.join(G2frame.dirname,'GSASIIsasd.save')
3867        file = open(G2frame.undosasd,'wb')
3868        PatternId = G2frame.PatternId
3869        for item in ['Models']:
3870            cPickle.dump(G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId,item)),file,1)
3871        file.close()
3872        G2frame.dataFrame.SasdUndo.Enable(True)
3873       
3874    def OnSelectFit(event):
3875        data['Current'] = fitSel.GetValue()
3876        wx.CallAfter(UpdateModelsGrid,G2frame,data)
3877       
3878    def OnCheckBox(event):
3879        Obj = event.GetEventObject()
3880        item,ind = Indx[Obj.GetId()]
3881        item[ind] = Obj.GetValue()
3882       
3883    def OnIntVal(event):
3884        Obj = event.GetEventObject()
3885        item,ind,minVal = Indx[Obj.GetId()]
3886        try:
3887            value = int(Obj.GetValue())
3888            if value <= minVal:
3889                raise ValueError
3890        except ValueError:
3891            value = item[ind]
3892        Obj.SetValue(str(value))
3893        item[ind] = value
3894
3895    def SizeSizer():
3896       
3897        def OnShape(event):
3898            data['Size']['Shape'][0] = partsh.GetValue()
3899            wx.CallAfter(UpdateModelsGrid,G2frame,data)
3900           
3901        def OnMethod(event):
3902            data['Size']['Method'] = method.GetValue()
3903            wx.CallAfter(UpdateModelsGrid,G2frame,data)
3904           
3905        def OnPartVal(event):
3906            try:
3907                val = max(0.0,float(partprm.GetValue()))
3908            except ValueError:
3909                val = 1
3910            data['Size']['Shape'][1] = val
3911            partprm.SetValue('%.3f'%(val))
3912           
3913        sizeSizer = wx.BoxSizer(wx.VERTICAL)
3914        sizeSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Size distribution parameters: '),0,WACV)
3915        binSizer = wx.FlexGridSizer(0,7,5,5)
3916        binSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' No. size bins: '),0,WACV)
3917        bins = ['50','100','150','200']
3918        nbins = wx.ComboBox(G2frame.dataDisplay,value=str(data['Size']['Nbins']),choices=bins,
3919            style=wx.CB_READONLY|wx.CB_DROPDOWN)
3920        Indx[nbins.GetId()] = [data['Size'],'Nbins',0]
3921        nbins.Bind(wx.EVT_COMBOBOX,OnIntVal)       
3922        binSizer.Add(nbins,0,WACV)
3923        binSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Min diam.: '),0,WACV)
3924        minDias = ['10','25','50','100','150','200']
3925        mindiam = wx.ComboBox(G2frame.dataDisplay,value=str(data['Size']['MinDiam']),choices=minDias,
3926            style=wx.CB_DROPDOWN)
3927        mindiam.Bind(wx.EVT_LEAVE_WINDOW,OnIntVal)
3928        mindiam.Bind(wx.EVT_TEXT_ENTER,OnIntVal)       
3929        mindiam.Bind(wx.EVT_KILL_FOCUS,OnIntVal)
3930        Indx[mindiam.GetId()] = [data['Size'],'MinDiam',0]
3931        binSizer.Add(mindiam,0,WACV)
3932        binSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Max diam.: '),0,WACV)
3933        maxDias = [str(1000*(i+1)) for i in range(10)]
3934        maxdiam = wx.ComboBox(G2frame.dataDisplay,value=str(data['Size']['MaxDiam']),choices=maxDias,
3935            style=wx.CB_DROPDOWN)
3936        maxdiam.Bind(wx.EVT_LEAVE_WINDOW,OnIntVal)
3937        maxdiam.Bind(wx.EVT_TEXT_ENTER,OnIntVal)       
3938        maxdiam.Bind(wx.EVT_KILL_FOCUS,OnIntVal)
3939        Indx[maxdiam.GetId()] = [data['Size'],'MaxDiam',0]
3940        binSizer.Add(maxdiam,0,WACV)
3941        logbins = wx.CheckBox(G2frame.dataDisplay,label='Log bins?')
3942        Indx[logbins.GetId()] = [data['Size'],'logBins']
3943        logbins.SetValue(data['Size']['logBins'])
3944        logbins.Bind(wx.EVT_CHECKBOX, OnCheckBox)
3945        binSizer.Add(logbins,0,WACV)
3946        sizeSizer.Add(binSizer,0)
3947        sizeSizer.Add((5,5),0)
3948        partSizer = wx.BoxSizer(wx.HORIZONTAL)
3949        partSizer.Add(wx.StaticText(G2frame.dataDisplay,label='Particle description: '),0,WACV)
3950        shapes = {'Spheroid':' Aspect ratio: ','Cylinder':' Diameter ','Cylinder AR':' Aspect ratio: ',
3951            'Unified sphere':'','Unified rod':' Diameter: ','Unified rod AR':' Aspect ratio: ',
3952            'Unified disk':' Thickness: '}
3953        partsh = wx.ComboBox(G2frame.dataDisplay,value=str(data['Size']['Shape'][0]),choices=shapes.keys(),
3954            style=wx.CB_READONLY|wx.CB_DROPDOWN)
3955        partsh.Bind(wx.EVT_COMBOBOX,OnShape)       
3956        partSizer.Add(partsh,0,WACV)
3957        if data['Size']['Shape'][0] not in ['Unified sphere',]:
3958            partSizer.Add(wx.StaticText(G2frame.dataDisplay,label=shapes[data['Size']['Shape'][0]]),0,WACV)
3959            partprm = wx.TextCtrl(G2frame.dataDisplay,value='%.3f'%(data['Size']['Shape'][1]),
3960                style=wx.TE_PROCESS_ENTER)
3961            partprm.Bind(wx.EVT_TEXT_ENTER,OnPartVal)       
3962            partprm.Bind(wx.EVT_KILL_FOCUS,OnPartVal)
3963            partSizer.Add(partprm,0,WACV)
3964        sizeSizer.Add(partSizer,0)
3965        sizeSizer.Add((5,5),0)
3966        fitSizer = wx.BoxSizer(wx.HORIZONTAL)
3967        methods = ['MaxEnt','IPG',]
3968        fitSizer.Add(wx.StaticText(G2frame.dataDisplay,label='Fitting method: '),0,WACV)
3969        method = wx.ComboBox(G2frame.dataDisplay,value=data['Size']['Method'],choices=methods,
3970            style=wx.CB_READONLY|wx.CB_DROPDOWN)
3971        method.Bind(wx.EVT_COMBOBOX,OnMethod)
3972        fitSizer.Add(method,0,WACV)
3973        iters = ['10','25','50','100','150','200']       
3974        fitSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' No. iterations: '),0,WACV)
3975        Method = data['Size']['Method']
3976        iter = wx.ComboBox(G2frame.dataDisplay,value=str(data['Size'][Method]['Niter']),choices=iters,
3977            style=wx.CB_READONLY|wx.CB_DROPDOWN)
3978        Indx[iter.GetId()] = [data['Size'][Method],'Niter',0]
3979        iter.Bind(wx.EVT_COMBOBOX,OnIntVal)
3980        fitSizer.Add(iter,0,WACV)
3981        if 'MaxEnt' in data['Size']['Method']:
3982            fitSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Log floor factor: '),0,WACV)
3983            floors = [str(-i) for i in range(9)]
3984            floor = wx.ComboBox(G2frame.dataDisplay,value=str(data['Size']['MaxEnt']['Sky']),choices=floors,
3985                style=wx.CB_READONLY|wx.CB_DROPDOWN)
3986            Indx[floor.GetId()] = [data['Size']['MaxEnt'],'Sky',-10]
3987            floor.Bind(wx.EVT_COMBOBOX,OnIntVal)
3988            fitSizer.Add(floor,0,WACV)
3989        elif 'IPG' in data['Size']['Method']:
3990            fitSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Q power weight (-1 for sigma): '),0,WACV)
3991            choices = ['-1','0','1','2','3','4']
3992            power = wx.ComboBox(G2frame.dataDisplay,value=str(data['Size']['IPG']['Power']),choices=choices,
3993                style=wx.CB_READONLY|wx.CB_DROPDOWN)
3994            Indx[power.GetId()] = [data['Size']['IPG'],'Power',-2]
3995            power.Bind(wx.EVT_COMBOBOX,OnIntVal)
3996            fitSizer.Add(power,0,WACV)
3997        sizeSizer.Add(fitSizer,0)
3998
3999        return sizeSizer
4000       
4001    def PartSizer():
4002       
4003        FormFactors = {'Sphere':{},'Spheroid':{'Aspect ratio':[1.0,False]},
4004            'Cylinder':{'Length':[100.,False]},'Cylinder diam':{'Diameter':[100.,False]},
4005            'Cylinder AR':{'Aspect ratio':[1.0,False]},'Unified sphere':{},
4006            'Unified rod':{'Length':[100.,False]},'Unified rod AR':{'Aspect ratio':[1.0,False]},
4007            'Unified disk':{'Thickness':[100.,False]},
4008            'Unified tube':{'Length':[100.,False],'Thickness':[10.,False]},}
4009               
4010        StructureFactors = {'Dilute':{},'Hard sphere':{'VolFr':[0.1,False],'Dist':[100.,False]},
4011            'Sticky hard sphere':{'VolFr':[0.1,False],'Dist':[100.,False],'epis':[0.05,False],'Sticky':[0.2,False]},
4012            'Square well':{'VolFr':[0.1,False],'Dist':[100.,False],'Depth':[0.1,False],'Width':[1.,False]},
4013            'InterPrecipitate':{'VolFr':[0.1,False],'Dist':[100.,False]},}
4014               
4015        ffDistChoices =  ['Sphere','Spheroid','Cylinder','Cylinder diam',
4016            'Cylinder AR','Unified sphere','Unified rod','Unified rod AR',
4017            'Unified disk','Unified tube',]
4018               
4019        ffMonoChoices = ['Sphere','Spheroid','Cylinder','Cylinder AR',]
4020       
4021        sfChoices = ['Dilute','Hard sphere','Sticky hard sphere','Square well','InterPrecipitate',]
4022           
4023        slMult = 1000.
4024                 
4025        def OnValue(event):
4026            Obj = event.GetEventObject()
4027            item,key,sldrObj = Indx[Obj.GetId()]
4028            try:
4029                value = float(Obj.GetValue())
4030                if value <= 0.:
4031                    raise ValueError
4032            except ValueError:
4033                value = item[key][0]
4034            item[key][0] = value
4035            Obj.SetValue('%.3g'%(value))
4036            if key in ['P','epis','Sticky','Depth','Width','VolFr','Dist']:
4037                sldrObj.SetValue(slMult*value)
4038            else:
4039                logv = np.log10(value)
4040                valMinMax = [logv-1,logv+1]
4041                sldrObj.SetRange(slMult*valMinMax[0],slMult*valMinMax[1])
4042                sldrObj.SetValue(slMult*logv)
4043            G2sasd.ModelFxn(Profile,ProfDict,Limits,Sample,data)
4044            RefreshPlots()
4045           
4046        def OnSelect(event):
4047            Obj = event.GetEventObject()
4048            item,key = Indx[Obj.GetId()]
4049            item[key] = Obj.GetValue()
4050            if 'Refine' not in Obj.GetLabel():
4051                if 'FormFact' in key :
4052                    item['FFargs'] = FormFactors[Obj.GetValue()]
4053                elif 'StrFact' in key:
4054                    item['SFargs'] = StructureFactors[Obj.GetValue()]
4055                wx.CallAfter(UpdateModelsGrid,G2frame,data)
4056                G2sasd.ModelFxn(Profile,ProfDict,Limits,Sample,data)
4057                RefreshPlots()
4058               
4059        def OnDelLevel(event):
4060            Obj = event.GetEventObject()
4061            item = Indx[Obj.GetId()]
4062            del data['Particle']['Levels'][item]
4063            wx.CallAfter(UpdateModelsGrid,G2frame,data)
4064            G2sasd.ModelFxn(Profile,ProfDict,Limits,Sample,data)
4065            RefreshPlots()
4066           
4067        def OnParmSlider(event):
4068            Obj = event.GetEventObject()
4069            item,key,pvObj = Indx[Obj.GetId()]
4070            slide = Obj.GetValue()
4071            if key in ['P','epis','Sticky','Depth','Width','VolFr','Dist']:
4072                value = float(slide/slMult)
4073            else:
4074                value = 10.**float(slide/slMult)
4075            item[key][0] = value
4076            pvObj.SetValue('%.3g'%(item[key][0]))
4077            G2sasd.ModelFxn(Profile,ProfDict,Limits,Sample,data)
4078            RefreshPlots()
4079           
4080        def SizeSizer():
4081            sizeSizer = wx.FlexGridSizer(0,4,5,5)
4082            sizeSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Distribution: '),0,WACV)
4083            Distchoice = ['LogNormal','Gaussian','LSW','Schulz-Zimm','Bragg','Unified','Porod','Monodisperse',]
4084            distChoice = wx.ComboBox(G2frame.dataDisplay,value=level['Controls']['DistType'],choices=Distchoice,
4085                style=wx.CB_READONLY|wx.CB_DROPDOWN)
4086            Indx[distChoice.GetId()] = [level['Controls'],'DistType']
4087            distChoice.Bind(wx.EVT_COMBOBOX,OnSelect)
4088            sizeSizer.Add(distChoice,0,WACV)    #put structure factor choices here
4089            if level['Controls']['DistType'] not in ['Bragg','Unified','Porod',]:
4090                sizeSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Form Factor: '),0,WACV)
4091                if 'Mono' in level['Controls']['DistType']:
4092                    ffChoice = wx.ComboBox(G2frame.dataDisplay,value=level['Controls']['FormFact'],choices=ffMonoChoices,
4093                        style=wx.CB_READONLY|wx.CB_DROPDOWN)
4094                else:
4095                    ffChoice = wx.ComboBox(G2frame.dataDisplay,value=level['Controls']['FormFact'],choices=ffDistChoices,
4096                        style=wx.CB_READONLY|wx.CB_DROPDOWN)
4097                Indx[ffChoice.GetId()] = [level['Controls'],'FormFact']
4098                ffChoice.Bind(wx.EVT_COMBOBOX,OnSelect)
4099                sizeSizer.Add(ffChoice,0,WACV)
4100               
4101                sizeSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Material: '),0,WACV)
4102                matSel = wx.ComboBox(G2frame.dataDisplay,value=level['Controls']['Material'],
4103                    choices=Substances['Substances'].keys(),style=wx.CB_READONLY|wx.CB_DROPDOWN)
4104                Indx[matSel.GetId()] = [level['Controls'],'Material']
4105                matSel.Bind(wx.EVT_COMBOBOX,OnSelect)       
4106                sizeSizer.Add(matSel,0,WACV) #do neutron test here?
4107                rho = Substances['Substances'][level['Controls']['Material']].get('XAnom density',0.0)
4108                level['Controls']['Contrast'] = contrast = (rho-rhoMat)**2                 
4109                sizeSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Resonant X-ray contrast: '),0,WACV)
4110                sizeSizer.Add(wx.StaticText(G2frame.dataDisplay,label=%.2f 10%scm%s'%(contrast,Pwr20,Pwrm4)),0,WACV)
4111                if 'Mono' not in level['Controls']['DistType']:
4112                    sizeSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Num. radii: '),0,WACV)
4113                    radii = ['25','50','75','100','200']
4114                    nRadii = wx.ComboBox(G2frame.dataDisplay,value=str(level['Controls']['NumPoints']),choices=radii,
4115                        style=wx.CB_READONLY|wx.CB_DROPDOWN)
4116                    Indx[nRadii.GetId()] = [level['Controls'],'NumPoints']
4117                    nRadii.Bind(wx.EVT_COMBOBOX,OnSelect