source: trunk/GSASIIpwdGUI.py @ 1834

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

redefine azimuthal angle in Sample Parms as the center of the azimuthal bin; the azimuthat angle in Instrument parms is defined as the mean angle for polarization (only 0-90 & slightly different)
some cosmetic changes to GUI displays
fix imports/G2pwd_fxye.py to handle multi time-maps found in HIPPO data & the slightly screwy one in HIPD data

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