source: trunk/GSASIIpwdGUI.py @ 1273

Last change on this file since 1273 was 1273, checked in by vondreele, 8 years ago

clean up SASD Model plotting
clean up form factor functions

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