source: trunk/GSASIIpwdGUI.py @ 1237

Last change on this file since 1237 was 1237, checked in by vondreele, 9 years ago

Allow changes to limits when in SASD Models
"fix" matplotlib warning message when log plot is hit with a mouse button event
There is still an underlying problem.
Mods to SASD Model to have scaled errors on data for fitting purposes - uses wtFactor
Start on size distribution fitting

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