source: trunk/GSASIIpwdGUI.py @ 1217

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

add reading of CheMin? tif & png files
continue work on small angle stuff

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