source: trunk/GSASIIgrid.py @ 721

Last change on this file since 721 was 721, checked in by vondreele, 13 years ago

add dist/angle calc for map peaks
unique peaks selects unique set from selected map PeaksUnique?
peaks falling near special positions are corrected to be on special position

  • Property svn:keywords set to Date Author Revision URL Id
File size: 106.6 KB
Line 
1# -*- coding: utf-8 -*-
2#GSASII - data display routines
3########### SVN repository information ###################
4# $Date: 2012-08-19 19:13:13 +0000 (Sun, 19 Aug 2012) $
5# $Author: vondreele $
6# $Revision: 721 $
7# $URL: trunk/GSASIIgrid.py $
8# $Id: GSASIIgrid.py 721 2012-08-19 19:13:13Z vondreele $
9########### SVN repository information ###################
10import wx
11import wx.grid as wg
12import time
13import cPickle
14import sys
15import numpy as np
16import os.path
17import wx.html        # could postpone this for quicker startup
18import webbrowser     # could postpone this for quicker startup
19import GSASIIpath
20GSASIIpath.SetVersionNumber("$Revision: 721 $")
21import GSASIIIO as G2IO
22import GSASIIplot as G2plt
23import GSASIIpwdGUI as G2pdG
24import GSASIIimgGUI as G2imG
25import GSASIIphsGUI as G2phG
26import GSASIIstruct as G2str
27import GSASIImapvars as G2mv
28
29# globals we will use later
30__version__ = None # gets overridden in GSASII.py
31path2GSAS2 = os.path.dirname(os.path.realpath(__file__)) # save location of this file
32helpLocDict = {}
33htmlPanel = None
34htmlFrame = None
35helpMode = 'browser'
36if sys.platform.lower().startswith('win'): helpMode = 'internal' # need a global control to set this
37   
38htmlFirstUse = True
39
40[ wxID_FOURCALC, wxID_FOURSEARCH, wxID_FOURCLEAR, wxID_PEAKSMOVE, wxID_PEAKSCLEAR, 
41    wxID_CHARGEFLIP, wxID_PEAKSUNIQUE, wxID_PEAKSDELETE, wxID_PEAKSDA,
42] = [wx.NewId() for item in range(9)]
43
44[ wxID_PWDRADD, wxID_HKLFADD, wxID_DATADELETE,
45] = [wx.NewId() for item in range(3)]
46
47[ wxID_ATOMSEDITADD, wxID_ATOMSEDITINSERT, wxID_ATOMSEDITDELETE, wxID_ATOMSREFINE, 
48    wxID_ATOMSMODIFY, wxID_ATOMSTRANSFORM, wxID_ATOMSTESTADD, wxID_ATONTESTINSERT,
49    wxID_RELOADDRAWATOMS,wxID_ATOMSDISAGL,
50] = [wx.NewId() for item in range(10)]
51
52[ wxID_DRAWATOMSTYLE, wxID_DRAWATOMLABEL, wxID_DRAWATOMCOLOR, wxID_DRAWATOMRESETCOLOR, 
53    wxID_DRAWVIEWPOINT, wxID_DRAWTRANSFORM, wxID_DRAWDELETE, wxID_DRAWFILLCELL, 
54    wxID_DRAWADDEQUIV, wxID_DRAWFILLCOORD, wxID_DRAWDISAGLTOR,  wxID_DRAWPLANE,
55] = [wx.NewId() for item in range(12)]
56
57[ wxID_DRAWRESTRBOND, wxID_DRAWRESTRANGLE, wxID_DRAWRESTRPLANE, wxID_DRAWRESTRCHIRAL,
58] = [wx.NewId() for item in range(4)]
59
60[ wxID_CLEARTEXTURE,wxID_REFINETEXTURE,
61] = [wx.NewId() for item in range(2)]
62
63[ wxID_PAWLEYLOAD, wxID_PAWLEYDELETE, wxID_PAWLEYESTIMATE,
64    wxID_PAWLEYUPDATE,
65] = [wx.NewId() for item in range(4)]
66
67[ wxID_IMCALIBRATE,wxID_IMRECALIBRATE,wxID_IMINTEGRATE, wxID_IMCLEARCALIB, 
68    wxID_IMCOPYCONTROLS, wxID_INTEGRATEALL, wxID_IMSAVECONTROLS, wxID_IMLOADCONTROLS,
69] = [wx.NewId() for item in range(8)]
70
71[ wxID_MASKCOPY, wxID_MASKSAVE, wxID_MASKLOAD,
72] = [wx.NewId() for item in range(3)]
73
74[ wxID_STRSTACOPY, wxID_STRSTAFIT, wxID_STRSTASAVE, wxID_STRSTALOAD,wxID_APPENDDZERO,
75] = [wx.NewId() for item in range(5)]
76
77[ wxID_BACKCOPY,wxID_LIMITCOPY,wxID_SAMPLECOPY, wxID_BACKFLAGCOPY, wxID_SAMPLEFLAGCOPY,
78    wxID_SAMPLESAVE, wxID_SAMPLELOAD,
79] = [wx.NewId() for item in range(7)]
80
81[ wxID_INSTPRMRESET,wxID_CHANGEWAVETYPE,wxID_INSTCOPY, wxID_INSTFLAGCOPY, wxID_INSTLOAD,
82    wxID_INSTSAVE,
83] = [wx.NewId() for item in range(6)]
84
85[ wxID_UNDO,wxID_LSQPEAKFIT,wxID_LSQONECYCLE,wxID_RESETSIGGAM,wxID_CLEARPEAKS,
86] = [wx.NewId() for item in range(5)]
87
88[  wxID_INDXRELOAD, wxID_INDEXPEAKS, wxID_REFINECELL, wxID_COPYCELL, wxID_MAKENEWPHASE,
89] = [wx.NewId() for item in range(5)]
90
91[ wxID_CONSTRAINTADD,wxID_EQUIVADD,wxID_HOLDADD,wxID_FUNCTADD,
92] = [wx.NewId() for item in range(4)]
93
94[ wxID_RESTRAINTADD,wxID_PWDANALYSIS, wxID_RESTSELPHASE,wxID_RESTDELETE,
95] = [wx.NewId() for item in range(4)]
96
97[ wxID_SAVESEQSEL,
98] = [wx.NewId() for item in range(1)]
99
100[ wxID_SELECTPHASE,
101] = [wx.NewId() for item in range(1)]
102
103[ wxID_PDFCOPYCONTROLS, wxID_PDFSAVECONTROLS, wxID_PDFLOADCONTROLS, 
104    wxID_PDFCOMPUTE, wxID_PDFCOMPUTEALL, wxID_PDFADDELEMENT, wxID_PDFDELELEMENT,
105] = [wx.NewId() for item in range(7)]
106
107VERY_LIGHT_GREY = wx.Colour(235,235,235)
108
109def ShowHelp(helpType,frame):
110    '''Called to bring up a web page for documentation.'''
111    global htmlFirstUse
112    # look up a definition for help info from dict
113    helplink = helpLocDict.get(helpType)
114    if helplink is None:
115        # no defined link to use, create a default based on key
116        helplink = 'gsasII.html#'+helpType.replace(' ','_')
117    helplink = os.path.join(path2GSAS2,'help',helplink)
118    if helpMode == 'internal':
119        try:
120            htmlPanel.LoadFile(helplink)
121            htmlFrame.Raise()
122        except:
123            htmlFrame = wx.Frame(frame, -1, size=(610, 510))
124            htmlFrame.Show(True)
125            htmlFrame.SetTitle("HTML Window") # N.B. reset later in LoadFile
126            htmlPanel = MyHtmlPanel(htmlFrame,-1)
127            htmlPanel.LoadFile(helplink)
128    else:
129        if htmlFirstUse:
130            webbrowser.open_new("file://"+helplink)
131            htmlFirstUse = False
132        else:
133            webbrowser.open("file://"+helplink, new=0, autoraise=True)
134
135class MyHelp(wx.Menu):
136    '''This class creates the contents of a help menu.
137    The menu will start with two entries:
138      'Help on <helpType>': where helpType is a reference to an HTML page to
139      be opened
140      About: opens an About dialog using OnHelpAbout. N.B. on the Mac this
141      gets moved to the App menu to be consistent with Apple style.
142    NOTE: the title for this menu should be '&Help' so the wx handles
143    it correctly. BHT
144    '''
145    def __init__(self,frame,title='',helpType=None,morehelpitems=[]):
146        wx.Menu.__init__(self,title)
147        self.HelpById = {}
148        self.frame = frame
149        # add a help item only when helpType is specified
150        if helpType is not None:
151            helpobj = self.Append(text='Help on '+helpType,
152                id=wx.ID_ANY, kind=wx.ITEM_NORMAL)
153            frame.Bind(wx.EVT_MENU, self.OnHelpById, helpobj)
154            self.HelpById[helpobj.GetId()] = helpType
155        for lbl,indx in morehelpitems:
156            helpobj = self.Append(text=lbl,
157                id=wx.ID_ANY, kind=wx.ITEM_NORMAL)
158            frame.Bind(wx.EVT_MENU, self.OnHelpById, helpobj)
159            self.HelpById[helpobj.GetId()] = indx
160        self.Append(help='', id=wx.ID_ABOUT, kind=wx.ITEM_NORMAL,
161            text='&About GSAS-II')
162        frame.Bind(wx.EVT_MENU, self.OnHelpAbout, id=wx.ID_ABOUT)
163
164    def OnHelpById(self,event):
165        '''Called when Help on... is pressed in a menu. Brings up
166        a web page for documentation.
167        '''
168        helpType = self.HelpById.get(event.GetId())
169        if helpType is None:
170            print 'Error: help lookup failed!',event.GetEventObject()
171            print 'id=',event.GetId()
172        else:
173            ShowHelp(helpType,self.frame)
174
175    def OnHelpAbout(self, event):
176        "Display an 'About GSAS-II' box"
177        global __version__
178        info = wx.AboutDialogInfo()
179        info.Name = 'GSAS-II'
180        info.Version = __version__ + ' Revision '+str(GSASIIpath.GetVersionNumber())
181        info.Copyright = '''
182Robert B. Von Dreele & Brian H. Toby
183Argonne National Laboratory(C)
184This product includes software developed
185by the UChicago Argonne, LLC, as
186Operator of Argonne National Laboratory.         '''
187        info.Description = '''
188General Structure Analysis System - GSAS-II
189'''
190        wx.AboutBox(info)
191
192class MyHtmlPanel(wx.Panel):
193    '''Defines a panel to display Help information'''
194    def __init__(self, frame, id):
195        self.frame = frame
196        wx.Panel.__init__(self, frame, id)
197        sizer = wx.BoxSizer(wx.VERTICAL)
198        back = wx.Button(self, -1, "Back")
199        back.Bind(wx.EVT_BUTTON, self.OnBack)
200        self.htmlwin = G2HtmlWindow(self, id, size=(750,450))
201        sizer.Add(self.htmlwin, 1,wx.EXPAND)
202        sizer.Add(back, 0, wx.ALIGN_LEFT, 0)
203        self.SetSizer(sizer)
204        sizer.Fit(frame)       
205        self.Bind(wx.EVT_SIZE,self.OnSize)
206    def OnSize(self,event):         #does the job but weirdly!!
207        anchor = self.htmlwin.GetOpenedAnchor()
208        if anchor:           
209            self.htmlwin.ScrollToAnchor(anchor)
210            wx.CallAfter(self.htmlwin.ScrollToAnchor,anchor)
211            event.Skip()
212    def OnBack(self, event):
213        self.htmlwin.HistoryBack()
214    def LoadFile(self,file):
215        pos = file.rfind('#')
216        if pos != -1:
217            helpfile = file[:pos]
218            helpanchor = file[pos+1:]
219        else:
220            helpfile = file
221            helpanchor = None
222        self.htmlwin.LoadPage(helpfile)
223        if helpanchor is not None:
224            self.htmlwin.ScrollToAnchor(helpanchor)
225            xs,ys = self.htmlwin.GetViewStart()
226            self.htmlwin.Scroll(xs,ys-1)
227
228class G2HtmlWindow(wx.html.HtmlWindow):
229    '''Displays help information in a primitive HTML browser type window
230    '''
231    def __init__(self, parent, *args, **kwargs):
232        self.parent = parent
233        wx.html.HtmlWindow.__init__(self, parent, *args, **kwargs)
234    def LoadPage(self, *args, **kwargs):
235        wx.html.HtmlWindow.LoadPage(self, *args, **kwargs)
236        self.TitlePage()
237    def OnLinkClicked(self, *args, **kwargs):
238        wx.html.HtmlWindow.OnLinkClicked(self, *args, **kwargs)
239        xs,ys = self.GetViewStart()
240        self.Scroll(xs,ys-1)
241        self.TitlePage()
242    def HistoryBack(self, *args, **kwargs):
243        wx.html.HtmlWindow.HistoryBack(self, *args, **kwargs)
244        self.TitlePage()
245    def TitlePage(self):
246        self.parent.frame.SetTitle(self.GetOpenedPage() + ' -- ' + 
247            self.GetOpenedPageTitle())
248
249class DataFrame(wx.Frame):
250
251    def _init_menus(self):
252       
253# define all GSAS-II menus       
254       
255        self.BlankMenu = wx.MenuBar()
256       
257# Controls
258        self.ControlsMenu = wx.MenuBar()
259        self.ControlsMenu.Append(menu=MyHelp(self,helpType='Controls'),title='&Help')
260       
261# Notebook
262        self.DataNotebookMenu = wx.MenuBar()
263        self.DataNotebookMenu.Append(menu=MyHelp(self,helpType='Notebook'),title='&Help')
264       
265# Comments
266        self.DataCommentsMenu = wx.MenuBar()
267        self.DataCommentsMenu.Append(menu=MyHelp(self,helpType='Comments'),title='&Help')
268       
269# Constraints
270        self.ConstraintMenu = wx.MenuBar()
271        self.ConstraintEdit = wx.Menu(title='')
272        self.ConstraintMenu.Append(menu=self.ConstraintEdit, title='Edit')
273        self.ConstraintMenu.Append(menu=MyHelp(self,helpType='Constraints'),title='&Help')
274        self.ConstraintEdit.Append(id=wxID_HOLDADD, kind=wx.ITEM_NORMAL,text='Add hold',
275            help='Add hold on a parameter value')
276        self.ConstraintEdit.Append(id=wxID_EQUIVADD, kind=wx.ITEM_NORMAL,text='Add equivalence',
277            help='Add equivalence between parameter values')
278        self.ConstraintEdit.Append(id=wxID_CONSTRAINTADD, kind=wx.ITEM_NORMAL,text='Add constraint',
279            help='Add constraint on parameter values')
280        self.ConstraintEdit.Append(id=wxID_FUNCTADD, kind=wx.ITEM_NORMAL,text='Add New Var',
281            help='Add variable composed of existing parameter')
282           
283# Restraints
284        self.RestraintMenu = wx.MenuBar()
285        self.RestraintEdit = wx.Menu(title='')
286        self.RestraintMenu.Append(menu=self.RestraintEdit, title='Edit')
287        self.RestraintMenu.Append(menu=MyHelp(self,helpType='Restraints'),title='&Help')
288        self.RestraintEdit.Append(id=wxID_RESTSELPHASE, kind=wx.ITEM_NORMAL,text='Select phase',
289            help='Select phase')
290        self.RestraintEdit.Append(id=wxID_RESTRAINTADD, kind=wx.ITEM_NORMAL,text='Add restraints',
291            help='Add restraints')
292        self.RestraintEdit.Append(id=wxID_RESTDELETE, kind=wx.ITEM_NORMAL,text='Delete restraints',
293            help='Delete selected restraints')
294           
295# Sequential results
296        self.SequentialMenu = wx.MenuBar()
297        self.SequentialFile = wx.Menu(title='')
298        self.SequentialMenu.Append(menu=self.SequentialFile, title='File')
299        self.SequentialMenu.Append(menu=MyHelp(self,helpType='Sequential'),title='&Help')
300        self.SequentialFile.Append(id=wxID_SAVESEQSEL, kind=wx.ITEM_NORMAL,text='Save...',
301            help='Save selected sequential refinement results')
302           
303# PDR
304        self.ErrorMenu = wx.MenuBar()
305        self.ErrorAnal = wx.Menu(title='')
306        self.ErrorMenu.Append(menu=self.ErrorAnal,title='Analysis')
307        self.ErrorMenu.Append(menu=MyHelp(self,helpType='PWD Analysis'),title='&Help')
308        self.ErrorAnal.Append(id=wxID_PWDANALYSIS,kind=wx.ITEM_NORMAL,text='Analyze',
309            help='Error analysis on ppowder pattern')
310           
311# PDR / Limits
312        self.LimitMenu = wx.MenuBar()
313        self.LimitEdit = wx.Menu(title='')
314        self.LimitMenu.Append(menu=self.LimitEdit, title='File')
315        self.LimitMenu.Append(menu=MyHelp(self,helpType='Limits'),title='&Help')
316        self.LimitEdit.Append(id=wxID_LIMITCOPY, kind=wx.ITEM_NORMAL,text='Copy',
317            help='Copy limits to other histograms')
318           
319# PDR / Background
320        self.BackMenu = wx.MenuBar()
321        self.BackEdit = wx.Menu(title='')
322        self.BackMenu.Append(menu=self.BackEdit, title='File')
323        self.BackMenu.Append(menu=MyHelp(self,helpType='Background'),title='&Help')
324        self.BackEdit.Append(id=wxID_BACKCOPY, kind=wx.ITEM_NORMAL,text='Copy',
325            help='Copy background parameters to other histograms')
326        self.BackEdit.Append(id=wxID_BACKFLAGCOPY, kind=wx.ITEM_NORMAL,text='Copy flags',
327            help='Copy background refinement flags to other histograms')
328           
329# PDR / Instrument Parameters
330        self.InstMenu = wx.MenuBar()
331        self.InstEdit = wx.Menu(title='')
332        self.InstMenu.Append(menu=self.InstEdit, title='Operations')
333        self.InstMenu.Append(menu=MyHelp(self,helpType='Instrument Parameters'),title='&Help')
334        self.InstEdit.Append(help='Reset instrument profile parameters to default', 
335            id=wxID_INSTLOAD, kind=wx.ITEM_NORMAL,text='Load profile...')
336        self.InstEdit.Append(help='Load instrument profile parameters from file', 
337            id=wxID_INSTSAVE, kind=wx.ITEM_NORMAL,text='Save profile...')
338        self.InstEdit.Append(help='Save instrument profile parameters to file', 
339            id=wxID_INSTPRMRESET, kind=wx.ITEM_NORMAL,text='Reset profile')
340        self.InstEdit.Append(help='Copy instrument profile parameters to other histograms', 
341            id=wxID_INSTCOPY, kind=wx.ITEM_NORMAL,text='Copy')
342        self.InstEdit.Append(id=wxID_INSTFLAGCOPY, kind=wx.ITEM_NORMAL,text='Copy flags',
343            help='Copy instrument parameter refinement flags to other histograms')
344        self.InstEdit.Append(help='Change radiation type (Ka12 - synch)', 
345            id=wxID_CHANGEWAVETYPE, kind=wx.ITEM_NORMAL,text='Change radiation')
346       
347# PDR / Sample Parameters
348        self.SampleMenu = wx.MenuBar()
349        self.SampleEdit = wx.Menu(title='')
350        self.SampleMenu.Append(menu=self.SampleEdit, title='File')
351        self.SampleMenu.Append(menu=MyHelp(self,helpType='Sample Parameters'),title='&Help')
352        self.SampleEdit.Append(id=wxID_SAMPLELOAD, kind=wx.ITEM_NORMAL,text='Load',
353            help='Load sample parameters from file')
354        self.SampleEdit.Append(id=wxID_SAMPLESAVE, kind=wx.ITEM_NORMAL,text='Save',
355            help='Save sample parameters to file')
356        self.SampleEdit.Append(id=wxID_SAMPLECOPY, kind=wx.ITEM_NORMAL,text='Copy',
357            help='Copy refinable sample parameters to other histograms')
358        self.SampleEdit.Append(id=wxID_SAMPLEFLAGCOPY, kind=wx.ITEM_NORMAL,text='Copy flags',
359            help='Copy sample parameter refinement flags to other histograms')
360
361# PDR / Peak List
362        self.PeakMenu = wx.MenuBar()
363        self.PeakEdit = wx.Menu(title='')
364        self.PeakMenu.Append(menu=self.PeakEdit, title='Peak Fitting')
365        self.PeakMenu.Append(menu=MyHelp(self,helpType='Peak List'),title='&Help')
366        self.UnDo = self.PeakEdit.Append(help='Undo last least squares refinement', 
367            id=wxID_UNDO, kind=wx.ITEM_NORMAL,text='UnDo')
368        self.PeakFit = self.PeakEdit.Append(id=wxID_LSQPEAKFIT, kind=wx.ITEM_NORMAL,text='LSQ PeakFit', 
369            help='Peak fitting via least-squares' )
370        self.PFOneCycle = self.PeakEdit.Append(id=wxID_LSQONECYCLE, kind=wx.ITEM_NORMAL,text='LSQ one cycle', 
371            help='One cycle of Peak fitting via least-squares' )
372        self.PeakEdit.Append(id=wxID_RESETSIGGAM, kind=wx.ITEM_NORMAL, 
373            text='Reset sig and gam',help='Reset sigma and gamma to global fit' )
374        self.PeakEdit.Append(id=wxID_CLEARPEAKS, kind=wx.ITEM_NORMAL,text='Clear peaks', 
375            help='Clear the peak list' )
376        self.UnDo.Enable(False)
377        self.PeakFit.Enable(False)
378        self.PFOneCycle.Enable(False)
379       
380# PDR / Index Peak List
381        self.IndPeaksMenu = wx.MenuBar()
382        self.IndPeaksEdit = wx.Menu(title='')
383        self.IndPeaksMenu.Append(menu=self.IndPeaksEdit,title='Operations')
384        self.IndPeaksMenu.Append(menu=MyHelp(self,helpType='Index Peak List'),title='&Help')
385        self.IndPeaksEdit.Append(help='Load/Reload index peaks from peak list',id=wxID_INDXRELOAD, 
386            kind=wx.ITEM_NORMAL,text='Load/Reload')
387       
388# PDR / Unit Cells List
389        self.IndexMenu = wx.MenuBar()
390        self.IndexEdit = wx.Menu(title='')
391        self.IndexMenu.Append(menu=self.IndexEdit, title='Cell Index/Refine')
392        self.IndexMenu.Append(menu=MyHelp(self,helpType='Unit Cells List'),title='&Help')
393        self.IndexPeaks = self.IndexEdit.Append(help='', id=wxID_INDEXPEAKS, kind=wx.ITEM_NORMAL,
394            text='Index Cell')
395        self.CopyCell = self.IndexEdit.Append( id=wxID_COPYCELL, kind=wx.ITEM_NORMAL,text='Copy Cell', 
396            help='Copy selected unit cell from indexing to cell refinement fields')
397        self.RefineCell = self.IndexEdit.Append( id=wxID_REFINECELL, kind=wx.ITEM_NORMAL, 
398            text='Refine Cell',help='Refine unit cell parameters from indexed peaks')
399        self.MakeNewPhase = self.IndexEdit.Append( id=wxID_MAKENEWPHASE, kind=wx.ITEM_NORMAL,
400            text='Make new phase',help='Make new phase from selected unit cell')
401        self.IndexPeaks.Enable(False)
402        self.CopyCell.Enable(False)
403        self.RefineCell.Enable(False)
404        self.MakeNewPhase.Enable(False)
405       
406# PDR / Reflection Lists
407        self.ReflMenu = wx.MenuBar()
408        self.ReflEdit = wx.Menu(title='')
409        self.ReflMenu.Append(menu=self.ReflEdit, title='Reflection List')
410        self.ReflMenu.Append(menu=MyHelp(self,helpType='Reflection List'),title='&Help')
411        self.SelectPhase = self.ReflEdit.Append(help='Select phase for reflection list',id=wxID_SELECTPHASE, 
412            kind=wx.ITEM_NORMAL,text='Select phase')
413       
414# IMG / Image Controls
415        self.ImageMenu = wx.MenuBar()
416        self.ImageEdit = wx.Menu(title='')
417        self.ImageMenu.Append(menu=self.ImageEdit, title='Operations')
418        self.ImageMenu.Append(menu=MyHelp(self,helpType='Image Controls'),title='&Help')
419        self.ImageEdit.Append(help='Calibrate detector by fitting to calibrant lines', 
420            id=wxID_IMCALIBRATE, kind=wx.ITEM_NORMAL,text='Calibrate')
421        self.ImageEdit.Append(help='Recalibrate detector by fitting to calibrant lines', 
422            id=wxID_IMRECALIBRATE, kind=wx.ITEM_NORMAL,text='Recalibrate')
423        self.ImageEdit.Append(help='Clear calibration data points and rings',id=wxID_IMCLEARCALIB, 
424            kind=wx.ITEM_NORMAL,text='Clear calibration')
425        self.ImageEdit.Append(help='Integrate selected image',id=wxID_IMINTEGRATE, 
426            kind=wx.ITEM_NORMAL,text='Integrate')
427        self.ImageEdit.Append(help='Integrate all images selected from list',id=wxID_INTEGRATEALL,
428            kind=wx.ITEM_NORMAL,text='Integrate all')
429        self.ImageEdit.Append(help='Copy image controls to other images', 
430            id=wxID_IMCOPYCONTROLS, kind=wx.ITEM_NORMAL,text='Copy Controls')
431        self.ImageEdit.Append(help='Save image controls to file', 
432            id=wxID_IMSAVECONTROLS, kind=wx.ITEM_NORMAL,text='Save Controls')
433        self.ImageEdit.Append(help='Load image controls from file', 
434            id=wxID_IMLOADCONTROLS, kind=wx.ITEM_NORMAL,text='Load Controls')
435           
436# IMG / Masks
437        self.MaskMenu = wx.MenuBar()
438        self.MaskEdit = wx.Menu(title='')
439        self.MaskMenu.Append(menu=self.MaskEdit, title='Operations')
440        self.MaskMenu.Append(menu=MyHelp(self,helpType='Image Masks'),title='&Help')
441        self.MaskEdit.Append(help='Copy mask to other images', 
442            id=wxID_MASKCOPY, kind=wx.ITEM_NORMAL,text='Copy mask')
443        self.MaskEdit.Append(help='Save mask to file', 
444            id=wxID_MASKSAVE, kind=wx.ITEM_NORMAL,text='Save mask')
445        self.MaskEdit.Append(help='Load mask from file', 
446            id=wxID_MASKLOAD, kind=wx.ITEM_NORMAL,text='Load mask')
447           
448# IMG / Stress/Strain
449
450        self.StrStaMenu = wx.MenuBar()
451        self.StrStaEdit = wx.Menu(title='')
452        self.StrStaMenu.Append(menu=self.StrStaEdit, title='Operations')
453        self.StrStaMenu.Append(menu=MyHelp(self,helpType='Stress/Strain'),title='&Help')
454        self.StrStaEdit.Append(help='Append d-zero for one ring', 
455            id=wxID_APPENDDZERO, kind=wx.ITEM_NORMAL,text='Append d-zero')
456        self.StrStaEdit.Append(help='Fit stress/strain data', 
457            id=wxID_STRSTAFIT, kind=wx.ITEM_NORMAL,text='Fit stress/strain')
458        self.StrStaEdit.Append(help='Copy stress/strain data to other images', 
459            id=wxID_STRSTACOPY, kind=wx.ITEM_NORMAL,text='Copy stress/strain')
460        self.StrStaEdit.Append(help='Save stress/strain data to file', 
461            id=wxID_STRSTASAVE, kind=wx.ITEM_NORMAL,text='Save stress/strain')
462        self.StrStaEdit.Append(help='Load stress/strain data from file', 
463            id=wxID_STRSTALOAD, kind=wx.ITEM_NORMAL,text='Load stress/strain')
464           
465# PDF / PDF Controls
466        self.PDFMenu = wx.MenuBar()
467        self.PDFEdit = wx.Menu(title='')
468        self.PDFMenu.Append(menu=self.PDFEdit, title='PDF Controls')
469        self.PDFMenu.Append(menu=MyHelp(self,helpType='PDF Controls'),title='&Help')
470        self.PDFEdit.Append(help='Add element to sample composition',id=wxID_PDFADDELEMENT, kind=wx.ITEM_NORMAL,
471            text='Add element')
472        self.PDFEdit.Append(help='Delete element from sample composition',id=wxID_PDFDELELEMENT, kind=wx.ITEM_NORMAL,
473            text='Delete element')
474        self.PDFEdit.Append(help='Copy PDF controls', id=wxID_PDFCOPYCONTROLS, kind=wx.ITEM_NORMAL,
475            text='Copy controls')
476#        self.PDFEdit.Append(help='Load PDF controls from file',id=wxID_PDFLOADCONTROLS, kind=wx.ITEM_NORMAL,
477#            text='Load Controls')
478#        self.PDFEdit.Append(help='Save PDF controls to file', id=wxID_PDFSAVECONTROLS, kind=wx.ITEM_NORMAL,
479#            text='Save controls')
480        self.PDFEdit.Append(help='Compute PDF', id=wxID_PDFCOMPUTE, kind=wx.ITEM_NORMAL,
481            text='Compute PDF')
482        self.PDFEdit.Append(help='Compute all PDFs', id=wxID_PDFCOMPUTEALL, kind=wx.ITEM_NORMAL,
483            text='Compute all PDFs')
484           
485# Phase / General tab
486        self.DataGeneral = wx.MenuBar()
487        self.GeneralCalc = wx.Menu(title='')
488        self.DataGeneral.Append(menu=self.GeneralCalc,title='Compute')
489        self.DataGeneral.Append(menu=MyHelp(self,helpType='General'),title='&Help')
490        self.GeneralCalc.Append(help='Compute Fourier map',id=wxID_FOURCALC, kind=wx.ITEM_NORMAL,
491            text='Fourier map')
492        self.GeneralCalc.Append(help='Search Fourier map',id=wxID_FOURSEARCH, kind=wx.ITEM_NORMAL,
493            text='Search map')
494        self.GeneralCalc.Append(help='Run charge flipping',id=wxID_CHARGEFLIP, kind=wx.ITEM_NORMAL,
495            text='Charge flipping')
496        self.GeneralCalc.Append(help='Clear map',id=wxID_FOURCLEAR, kind=wx.ITEM_NORMAL,
497            text='Clear map')
498       
499# Phase / Data tab
500        self.DataMenu = wx.MenuBar()
501        self.DataEdit = wx.Menu(title='')
502        self.DataMenu.Append(menu=self.DataEdit, title='Edit')
503        self.DataMenu.Append(menu=MyHelp(self,helpType='Data'),title='&Help')
504        self.DataEdit.Append(id=wxID_PWDRADD, kind=wx.ITEM_NORMAL,text='Add powder histograms',
505            help='Select new powder histograms to be used for this phase')
506        self.DataEdit.Append(id=wxID_HKLFADD, kind=wx.ITEM_NORMAL,text='Add single crystal histograms',
507            help='Select new single crystal histograms to be used for this phase')
508        self.DataEdit.Append(id=wxID_DATADELETE, kind=wx.ITEM_NORMAL,text='Delete histograms',
509            help='Delete histograms from use for this phase')
510           
511# Phase / Atoms tab
512        self.AtomsMenu = wx.MenuBar()
513        self.AtomEdit = wx.Menu(title='')
514        self.AtomCompute = wx.Menu(title='')
515        self.AtomsMenu.Append(menu=self.AtomEdit, title='Edit')
516        self.AtomsMenu.Append(menu=self.AtomCompute, title='Compute')
517        self.AtomsMenu.Append(menu=MyHelp(self,helpType='Atoms'),title='&Help')
518        self.AtomEdit.Append(id=wxID_ATOMSEDITADD, kind=wx.ITEM_NORMAL,text='Append atom',
519            help='Inserted as an H atom')
520        self.AtomEdit.Append(id=wxID_ATOMSTESTADD, kind=wx.ITEM_NORMAL,text='Append test point',
521            help='Inserted as an H atom')
522        self.AtomEdit.Append(id=wxID_ATOMSEDITINSERT, kind=wx.ITEM_NORMAL,text='Insert atom',
523            help='Select atom row to insert before; inserted as an H atom')
524        self.AtomEdit.Append(id=wxID_ATONTESTINSERT, kind=wx.ITEM_NORMAL,text='Insert test point',
525            help='Select atom row to insert before; inserted as an H atom')
526        self.AtomEdit.Append(id=wxID_ATOMSEDITDELETE, kind=wx.ITEM_NORMAL,text='Delete atom',
527            help='Select atoms to delete first')
528        self.AtomEdit.Append(id=wxID_ATOMSREFINE, kind=wx.ITEM_NORMAL,text='Set atom refinement flags',
529            help='Select atoms to refine first')
530        self.AtomEdit.Append(id=wxID_ATOMSMODIFY, kind=wx.ITEM_NORMAL,text='Modify atom parameters',
531            help='Select atoms to modify first')
532        self.AtomEdit.Append(id=wxID_ATOMSTRANSFORM, kind=wx.ITEM_NORMAL,text='Transform atoms',
533            help='Select atoms to transform first')
534        self.AtomEdit.Append(id=wxID_RELOADDRAWATOMS, kind=wx.ITEM_NORMAL,text='Reload draw atoms',
535            help='Reload atom drawing list')
536        self.AtomCompute.Append(id=wxID_ATOMSDISAGL, kind=wx.ITEM_NORMAL,text='Distances & Angles',
537            help='Compute distances & angles for selected atoms')
538                 
539# Phase / Draw Options tab
540        self.DataDrawOptions = wx.MenuBar()
541        self.DataDrawOptions.Append(menu=MyHelp(self,helpType='Draw Options'),title='&Help')
542       
543# Phase / Draw Atoms tab
544        self.DrawAtomsMenu = wx.MenuBar()
545        self.DrawAtomEdit = wx.Menu(title='')
546        self.DrawAtomCompute = wx.Menu(title='')
547        self.DrawAtomRestraint = wx.Menu(title='')
548        self.DrawAtomsMenu.Append(menu=self.DrawAtomEdit, title='Edit')
549        self.DrawAtomsMenu.Append(menu=self.DrawAtomCompute,title='Compute')
550        self.DrawAtomsMenu.Append(menu=self.DrawAtomRestraint, title='Restraints')
551        self.DrawAtomsMenu.Append(menu=MyHelp(self,helpType='Draw Atoms'),title='&Help')
552        self.DrawAtomEdit.Append(id=wxID_DRAWATOMSTYLE, kind=wx.ITEM_NORMAL,text='Atom style',
553            help='Select atoms first')
554        self.DrawAtomEdit.Append(id=wxID_DRAWATOMLABEL, kind=wx.ITEM_NORMAL,text='Atom label',
555            help='Select atoms first')
556        self.DrawAtomEdit.Append(id=wxID_DRAWATOMCOLOR, kind=wx.ITEM_NORMAL,text='Atom color',
557            help='Select atoms first')
558        self.DrawAtomEdit.Append(id=wxID_DRAWATOMRESETCOLOR, kind=wx.ITEM_NORMAL,text='Reset atom colors',
559            help='Resets all atom colors to defaults')
560        self.DrawAtomEdit.Append(id=wxID_DRAWVIEWPOINT, kind=wx.ITEM_NORMAL,text='View point',
561            help='View point is 1st atom selected')
562        self.DrawAtomEdit.Append(id=wxID_DRAWADDEQUIV, kind=wx.ITEM_NORMAL,text='Add atoms',
563            help='Add symmetry & cell equivalents to drawing set from selected atoms')
564        self.DrawAtomEdit.Append(id=wxID_DRAWTRANSFORM, kind=wx.ITEM_NORMAL,text='Transform atoms',
565            help='Transform selected atoms by symmetry & cell translations')
566        self.DrawAtomEdit.Append(id=wxID_DRAWFILLCOORD, kind=wx.ITEM_NORMAL,text='Fill CN-sphere',
567            help='Fill coordination sphere for selected atoms')           
568        self.DrawAtomEdit.Append(id=wxID_DRAWFILLCELL, kind=wx.ITEM_NORMAL,text='Fill unit cell',
569            help='Fill unit cell with selected atoms')
570        self.DrawAtomEdit.Append(id=wxID_DRAWDELETE, kind=wx.ITEM_NORMAL,text='Delete atoms',
571            help='Delete atoms from drawing set')
572        self.DrawAtomCompute.Append(id=wxID_DRAWDISAGLTOR, kind=wx.ITEM_NORMAL,text='Dist. Ang. Tors.',
573            help='Compute distance, angle or torsion for 2-4 selected atoms')   
574        self.DrawAtomCompute.Append(id=wxID_DRAWPLANE, kind=wx.ITEM_NORMAL,text='Best plane',
575            help='Compute best plane for 4+ selected atoms')   
576        self.DrawAtomRestraint.Append(id=wxID_DRAWRESTRBOND, kind=wx.ITEM_NORMAL,text='Add bond restraint',
577            help='Add bond restraint for selected atoms (2)')
578        self.DrawAtomRestraint.Append(id=wxID_DRAWRESTRANGLE, kind=wx.ITEM_NORMAL,text='Add angle restraint',
579            help='Add angle restraint for selected atoms (3: one end 1st)')
580        self.DrawAtomRestraint.Append(id=wxID_DRAWRESTRPLANE, kind=wx.ITEM_NORMAL,text='Add plane restraint',
581            help='Add plane restraint for selected atoms (4+)')
582        self.DrawAtomRestraint.Append(id=wxID_DRAWRESTRCHIRAL, kind=wx.ITEM_NORMAL,text='Add chiral restraint',
583            help='Add chiral restraint for selected atoms (4: center atom 1st)')
584           
585# Phase / Texture tab
586        self.TextureMenu = wx.MenuBar()
587        self.TextureEdit = wx.Menu(title='')
588        self.TextureMenu.Append(menu=self.TextureEdit, title='Texture')
589        self.TextureMenu.Append(menu=MyHelp(self,helpType='Texture'),title='&Help')
590        self.TextureEdit.Append(id=wxID_REFINETEXTURE, kind=wx.ITEM_NORMAL,text='Refine texture', 
591            help='Refine the texture coefficients from sequential Pawley results')
592        self.TextureEdit.Append(id=wxID_CLEARTEXTURE, kind=wx.ITEM_NORMAL,text='Clear texture', 
593            help='Clear the texture coefficients' )
594           
595# Phase / Pawley tab
596        self.PawleyMenu = wx.MenuBar()
597        self.PawleyEdit = wx.Menu(title='')
598        self.PawleyMenu.Append(menu=self.PawleyEdit,title='Operations')
599        self.PawleyMenu.Append(menu=MyHelp(self,helpType='Pawley'),title='&Help')
600        self.PawleyEdit.Append(id=wxID_PAWLEYLOAD, kind=wx.ITEM_NORMAL,text='Pawley create',
601            help='Initialize Pawley reflection list')
602        self.PawleyEdit.Append(id=wxID_PAWLEYESTIMATE, kind=wx.ITEM_NORMAL,text='Pawley estimate',
603            help='Estimate initial Pawley intensities')
604        self.PawleyEdit.Append(id=wxID_PAWLEYUPDATE, kind=wx.ITEM_NORMAL,text='Pawley update',
605            help='Update Pawley intensities from reflection list')
606        self.PawleyEdit.Append(id=wxID_PAWLEYDELETE, kind=wx.ITEM_NORMAL,text='Pawley delete',
607            help='Delete Pawley reflection list')
608           
609# Phase / Map peaks tab
610        self.MapPeaksMenu = wx.MenuBar()
611        self.MapPeaksEdit = wx.Menu(title='')
612        self.MapPeaksMenu.Append(menu=self.MapPeaksEdit, title='Map peaks')
613        self.MapPeaksMenu.Append(menu=MyHelp(self,helpType='Map peaks'),title='&Help')
614        self.MapPeaksEdit.Append(id=wxID_PEAKSMOVE, kind=wx.ITEM_NORMAL,text='Move peaks', 
615            help='Move selected peaks to atom list')
616        self.MapPeaksEdit.Append(id=wxID_PEAKSDA, kind=wx.ITEM_NORMAL,text='Calc dist/ang', 
617            help='Calculate distance or angle for selection')
618        self.MapPeaksEdit.Append(id=wxID_PEAKSUNIQUE, kind=wx.ITEM_NORMAL,text='Unique peaks', 
619            help='Select unique set')
620        self.MapPeaksEdit.Append(id=wxID_PEAKSDELETE, kind=wx.ITEM_NORMAL,text='Delete peaks', 
621            help='Delete selected peaks')
622        self.MapPeaksEdit.Append(id=wxID_PEAKSCLEAR, kind=wx.ITEM_NORMAL,text='Clear peaks', 
623            help='Clear the map peak list')
624           
625# end of GSAS-II menu definitions
626       
627    def _init_ctrls(self, parent,name=None,size=None,pos=None):
628        wx.Frame.__init__(self,parent=parent,
629            style=wx.DEFAULT_FRAME_STYLE | wx.FRAME_FLOAT_ON_PARENT ^ wx.CLOSE_BOX,
630            size=size,pos=pos,title='GSAS-II data display')
631        self._init_menus()
632        if name:
633            self.SetLabel(name)
634        self.Show()
635       
636    def __init__(self,parent,data=None,name=None, size=None,pos=None):
637        self._init_ctrls(parent,name,size,pos)
638        self.data = data
639        clientSize = wx.ClientDisplayRect()
640        Size = self.GetSize()
641        xPos = clientSize[2]-Size[0]
642        self.SetPosition(wx.Point(xPos,clientSize[1]+250))
643        self.AtomGrid = []
644        self.selectedRow = 0
645       
646    def setSizePosLeft(self,Width):
647        clientSize = wx.ClientDisplayRect()
648        Width[1] = min(Width[1],clientSize[2]-300)
649        Width[0] = max(Width[0],300)
650        self.SetSize(Width)
651#        self.SetPosition(wx.Point(clientSize[2]-Width[0],clientSize[1]+250))
652       
653    def Clear(self):
654        self.ClearBackground()
655        self.DestroyChildren()
656                   
657class GSNoteBook(wx.Notebook):
658    def __init__(self, parent, name='',size = None):
659        wx.Notebook.__init__(self, parent, -1, name=name, style= wx.BK_TOP)
660        if size: self.SetSize(size)
661                                                     
662    def Clear(self):       
663        GSNoteBook.DeleteAllPages(self)
664       
665    def FindPage(self,name):
666        numPage = self.GetPageCount()
667        for page in range(numPage):
668            if self.GetPageText(page) == name:
669                return page
670       
671class GSGrid(wg.Grid):
672    def __init__(self, parent, name=''):
673        wg.Grid.__init__(self,parent,-1,name=name)                   
674        self.SetSize(parent.GetClientSize())
675           
676    def Clear(self):
677        wg.Grid.ClearGrid(self)
678       
679    def SetCellStyle(self,r,c,color="white",readonly=True):
680        self.SetCellBackgroundColour(r,c,color)
681        self.SetReadOnly(r,c,isReadOnly=readonly)
682       
683    def GetSelection(self):
684        #this is to satisfy structure drawing stuff in G2plt when focus changes
685        return None
686                       
687class Table(wg.PyGridTableBase):
688    def __init__(self, data=[], rowLabels=None, colLabels=None, types = None):
689        wg.PyGridTableBase.__init__(self)
690        self.colLabels = colLabels
691        self.rowLabels = rowLabels
692        self.dataTypes = types
693        self.data = data
694       
695    def AppendRows(self, numRows=1):
696        self.data.append([])
697        return True
698       
699    def CanGetValueAs(self, row, col, typeName):
700        if self.dataTypes:
701            colType = self.dataTypes[col].split(':')[0]
702            if typeName == colType:
703                return True
704            else:
705                return False
706        else:
707            return False
708
709    def CanSetValueAs(self, row, col, typeName):
710        return self.CanGetValueAs(row, col, typeName)
711
712    def DeleteRow(self,pos):
713        data = self.GetData()
714        self.SetData([])
715        new = []
716        for irow,row in enumerate(data):
717            if irow <> pos:
718                new.append(row)
719        self.SetData(new)
720       
721    def GetColLabelValue(self, col):
722        if self.colLabels:
723            return self.colLabels[col]
724           
725    def GetData(self):
726        data = []
727        for row in range(self.GetNumberRows()):
728            data.append(self.GetRowValues(row))
729        return data
730       
731    def GetNumberCols(self):
732        try:
733            return len(self.colLabels)
734        except TypeError:
735            return None
736       
737    def GetNumberRows(self):
738        return len(self.data)
739       
740    def GetRowLabelValue(self, row):
741        if self.rowLabels:
742            return self.rowLabels[row]
743       
744    def GetColValues(self, col):
745        data = []
746        for row in range(self.GetNumberRows()):
747            data.append(self.GetValue(row, col))
748        return data
749       
750    def GetRowValues(self, row):
751        data = []
752        for col in range(self.GetNumberCols()):
753            data.append(self.GetValue(row, col))
754        return data
755       
756    def GetTypeName(self, row, col):
757        try:
758            return self.dataTypes[col]
759        except TypeError:
760            return None
761
762    def GetValue(self, row, col):
763        try:
764            return self.data[row][col]
765        except IndexError:
766            return None
767           
768    def InsertRows(self, pos, rows):
769        for row in range(rows):
770            self.data.insert(pos,[])
771            pos += 1
772       
773    def IsEmptyCell(self,row,col):
774        try:
775            return not self.data[row][col]
776        except IndexError:
777            return True
778       
779    def OnKeyPress(self, event):
780        dellist = self.GetSelectedRows()
781        if event.GetKeyCode() == wx.WXK_DELETE and dellist:
782            grid = self.GetView()
783            for i in dellist: grid.DeleteRow(i)
784               
785    def SetColLabelValue(self, col, label):
786        numcols = self.GetNumberCols()
787        if col > numcols-1:
788            self.colLabels.append(label)
789        else:
790            self.colLabels[col]=label
791       
792    def SetData(self,data):
793        for row in range(len(data)):
794            self.SetRowValues(row,data[row])
795               
796    def SetRowLabelValue(self, row, label):
797        self.rowLabels[row]=label
798           
799    def SetRowValues(self,row,data):
800        self.data[row] = data
801           
802    def SetValue(self, row, col, value):
803        def innerSetValue(row, col, value):
804            try:
805                self.data[row][col] = value
806            except TypeError:
807                return
808            except IndexError:
809                print row,col,value
810                # add a new row
811                if row > self.GetNumberRows():
812                    self.data.append([''] * self.GetNumberCols())
813                elif col > self.GetNumberCols():
814                    for row in range(self.GetNumberRows):
815                        self.data[row].append('')
816                print self.data
817                self.data[row][col] = value
818        innerSetValue(row, col, value)
819               
820def UpdateNotebook(G2frame,data):       
821    if data:
822        G2frame.dataFrame.SetLabel('Notebook')
823        G2frame.dataDisplay = wx.TextCtrl(parent=G2frame.dataFrame,size=G2frame.dataFrame.GetClientSize(),
824            style=wx.TE_MULTILINE|wx.TE_PROCESS_ENTER | wx.TE_DONTWRAP)
825        for line in data:
826            G2frame.dataDisplay.AppendText(line+"\n")
827            G2frame.dataDisplay.AppendText('Notebook entry @ '+time.ctime()+"\n")
828           
829def UpdateControls(G2frame,data):
830    #patch
831    if 'deriv type' not in data:
832        data = {}
833        data['deriv type'] = 'analytic Hessian'
834        data['min dM/M'] = 0.0001
835        data['shift factor'] = 1.
836        data['max cyc'] = 3       
837        data['F**2'] = True
838        data['minF/sig'] = 0
839    if 'shift factor' not in data:
840        data['shift factor'] = 1.
841    if 'max cyc' not in data:
842        data['max cyc'] = 3
843    if 'F**2' not in data:
844        data['F**2'] = True
845        data['minF/sig'] = 0
846    #end patch
847    def SeqSizer():
848       
849        def OnSelectData(event):
850            choices = ['All',]+GetPatternTreeDataNames(G2frame,['PWDR',])
851            sel = []
852            if 'Seq Data' in data:
853                for item in data['Seq Data']:
854                    sel.append(choices.index(item))
855            names = []
856            dlg = wx.MultiChoiceDialog(G2frame,'Select data:','Sequential refinement',choices)
857            dlg.SetSelections(sel)
858            if dlg.ShowModal() == wx.ID_OK:
859                sel = dlg.GetSelections()
860                for i in sel: names.append(choices[i])
861                if 'All' in names:
862                    names = choices[1:]
863                data['Seq Data'] = names               
864            dlg.Destroy()
865            reverseSel.Enable(True)
866           
867        def OnReverse(event):
868            data['Reverse Seq'] = reverseSel.GetValue()
869                   
870        seqSizer = wx.BoxSizer(wx.HORIZONTAL)
871        seqSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Sequential Refinement Powder Data: '),0,wx.ALIGN_CENTER_VERTICAL)
872        selSeqData = wx.Button(G2frame.dataDisplay,-1,label=' Select data')
873        selSeqData.Bind(wx.EVT_BUTTON,OnSelectData)
874        seqSizer.Add(selSeqData,0,wx.ALIGN_CENTER_VERTICAL)
875        seqSizer.Add((5,0),0)
876        reverseSel = wx.CheckBox(G2frame.dataDisplay,-1,label=' Reverse order?')
877        reverseSel.Bind(wx.EVT_CHECKBOX,OnReverse)
878        if 'Seq Data' not in data:
879            reverseSel.Enable(False)
880        if 'Reverse Seq' in data:
881            reverseSel.SetValue(data['Reverse Seq'])
882        seqSizer.Add(reverseSel,0,wx.ALIGN_CENTER_VERTICAL)
883        return seqSizer
884       
885    def LSSizer():       
886       
887        def OnDerivType(event):
888            data['deriv type'] = derivSel.GetValue()
889            derivSel.SetValue(data['deriv type'])
890            wx.CallAfter(UpdateControls,G2frame,data)
891           
892        def OnConvergence(event):
893            try:
894                value = max(1.e-9,min(1.0,float(Cnvrg.GetValue())))
895            except ValueError:
896                value = 0.0001
897            data['min dM/M'] = value
898            Cnvrg.SetValue('%.2g'%(value))
899           
900        def OnMaxCycles(event):
901            data['max cyc'] = int(maxCyc.GetValue())
902            maxCyc.SetValue(str(data['max cyc']))
903                       
904        def OnFactor(event):
905            try:
906                value = min(max(float(Factr.GetValue()),0.00001),100.)
907            except ValueError:
908                value = 1.0
909            data['shift factor'] = value
910            Factr.SetValue('%.5f'%(value))
911           
912        def OnFsqRef(event):
913            data['F**2'] = fsqRef.GetValue()
914       
915        def OnMinSig(event):
916            try:
917                value = min(max(float(minSig.GetValue()),0.),5.)
918            except ValueError:
919                value = 1.0
920            data['minF/sig'] = value
921            minSig.SetValue('%.2f'%(value))
922
923        LSSizer = wx.FlexGridSizer(cols=4,vgap=5,hgap=5)
924        LSSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Refinement derivatives: '),0,wx.ALIGN_CENTER_VERTICAL)
925        Choice=['analytic Jacobian','numeric','analytic Hessian']
926        derivSel = wx.ComboBox(parent=G2frame.dataDisplay,value=data['deriv type'],choices=Choice,
927            style=wx.CB_READONLY|wx.CB_DROPDOWN)
928        derivSel.SetValue(data['deriv type'])
929        derivSel.Bind(wx.EVT_COMBOBOX, OnDerivType)
930           
931        LSSizer.Add(derivSel,0,wx.ALIGN_CENTER_VERTICAL)
932        LSSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Min delta-M/M: '),0,wx.ALIGN_CENTER_VERTICAL)
933        Cnvrg = wx.TextCtrl(G2frame.dataDisplay,-1,value='%.2g'%(data['min dM/M']),style=wx.TE_PROCESS_ENTER)
934        Cnvrg.Bind(wx.EVT_TEXT_ENTER,OnConvergence)
935        Cnvrg.Bind(wx.EVT_KILL_FOCUS,OnConvergence)
936        LSSizer.Add(Cnvrg,0,wx.ALIGN_CENTER_VERTICAL)
937        if 'Hessian' in data['deriv type']:
938            LSSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Max cycles: '),0,wx.ALIGN_CENTER_VERTICAL)
939            Choice = ['0','1','2','3','5','10','15','20']
940            maxCyc = wx.ComboBox(parent=G2frame.dataDisplay,value=str(data['max cyc']),choices=Choice,
941                style=wx.CB_READONLY|wx.CB_DROPDOWN)
942            maxCyc.SetValue(str(data['max cyc']))
943            maxCyc.Bind(wx.EVT_COMBOBOX, OnMaxCycles)
944            LSSizer.Add(maxCyc,0,wx.ALIGN_CENTER_VERTICAL)
945        else:
946            LSSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Initial shift factor: '),0,wx.ALIGN_CENTER_VERTICAL)
947            Factr = wx.TextCtrl(G2frame.dataDisplay,-1,value='%.5f'%(data['shift factor']),style=wx.TE_PROCESS_ENTER)
948            Factr.Bind(wx.EVT_TEXT_ENTER,OnFactor)
949            Factr.Bind(wx.EVT_KILL_FOCUS,OnFactor)
950            LSSizer.Add(Factr,0,wx.ALIGN_CENTER_VERTICAL)
951        if G2frame.Sngl:
952            LSSizer.Add((1,0),)
953            LSSizer.Add((1,0),)
954            fsqRef = wx.CheckBox(G2frame.dataDisplay,-1,label='Refine HKLF as F^2? ')
955            fsqRef.SetValue(data['F**2'])
956            fsqRef.Bind(wx.EVT_CHECKBOX,OnFsqRef)
957            LSSizer.Add(fsqRef,0,wx.ALIGN_CENTER_VERTICAL)
958            LSSizer.Add(wx.StaticText(G2frame.dataDisplay,-1,label='Min obs/sig (0-5): '),0,wx.ALIGN_CENTER_VERTICAL)
959            minSig = wx.TextCtrl(G2frame.dataDisplay,-1,value='%.2f'%(data['minF/sig']),style=wx.TE_PROCESS_ENTER)
960            minSig.Bind(wx.EVT_TEXT_ENTER,OnMinSig)
961            minSig.Bind(wx.EVT_KILL_FOCUS,OnMinSig)
962            LSSizer.Add(minSig,0,wx.ALIGN_CENTER_VERTICAL)
963        return LSSizer
964       
965    if G2frame.dataDisplay:
966        G2frame.dataDisplay.Destroy()
967    if not G2frame.dataFrame.GetStatusBar():
968        Status = G2frame.dataFrame.CreateStatusBar()
969        Status.SetStatusText('')
970    G2frame.dataFrame.SetLabel('Controls')
971    G2frame.dataDisplay = wx.Panel(G2frame.dataFrame)
972    G2frame.dataFrame.SetMenuBar(G2frame.dataFrame.ControlsMenu)
973    mainSizer = wx.BoxSizer(wx.VERTICAL)
974    mainSizer.Add((5,5),0)
975    mainSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Refinement Controls:'),0,wx.ALIGN_CENTER_VERTICAL)   
976    mainSizer.Add(LSSizer())
977    mainSizer.Add((5,5),0)
978    mainSizer.Add(SeqSizer())
979    mainSizer.Add((5,5),0)
980       
981    mainSizer.Layout()   
982    G2frame.dataDisplay.SetSizer(mainSizer)
983    G2frame.dataDisplay.SetSize(mainSizer.Fit(G2frame.dataFrame))
984    G2frame.dataFrame.setSizePosLeft(mainSizer.Fit(G2frame.dataFrame))
985     
986def UpdateComments(G2frame,data):                   
987    G2frame.dataFrame.SetLabel('Comments')
988    G2frame.dataDisplay = wx.TextCtrl(parent=G2frame.dataFrame,size=G2frame.dataFrame.GetClientSize(),
989        style=wx.TE_MULTILINE|wx.TE_PROCESS_ENTER | wx.TE_DONTWRAP)
990    for line in data:
991        if line[-1] == '\n':
992            G2frame.dataDisplay.AppendText(line)
993        else:
994            G2frame.dataDisplay.AppendText(line+'\n')
995           
996def UpdateSeqResults(G2frame,data):
997    """
998    input:
999        data - dictionary
1000            'histNames' - list of histogram names in order as processed by Sequential Refinement
1001            'varyList' - list of variables - identical over all refinements insequence
1002            histName - dictionaries for all data sets processed:
1003                'variables'- result[0] from leastsq call
1004                'varyList' - list of variables; same as above
1005                'sig' - esds for variables
1006                'covMatrix' - covariance matrix from individual refinement
1007                'title' - histogram name; same as dict item name
1008                'newAtomDict' - new atom parameters after shifts applied
1009                'newCellDict' - new cell parameters after shifts to A0-A5 applied'
1010    """
1011    if not data:
1012        print 'No sequential refinement results'
1013        return
1014    histNames = data['histNames']
1015       
1016    def GetSampleParms():
1017        sampleParmDict = {'Temperature':[],'Pressure':[],'Humidity':[],'Voltage':[],'Force':[],}
1018        sampleParm = {}
1019        for name in histNames:
1020            Id = GetPatternTreeItemId(G2frame,G2frame.root,name)
1021            sampleData = G2frame.PatternTree.GetItemPyData(GetPatternTreeItemId(G2frame,Id,'Sample Parameters'))
1022            for item in sampleParmDict:
1023                sampleParmDict[item].append(sampleData[item])
1024        for item in sampleParmDict:
1025            frstValue = sampleParmDict[item][0]
1026            if np.any(np.array(sampleParmDict[item])-frstValue):
1027                sampleParm[item] = sampleParmDict[item]           
1028        return sampleParm
1029           
1030    def GetRwps():
1031        Rwps = []
1032        for name in histNames:
1033            Rwps.append(data[name]['Rvals']['Rwp'])
1034        return Rwps
1035           
1036    def GetSigData(parm):
1037        sigData = []
1038        for name in histNames:
1039            sigList = data[name]['sig']
1040            if colLabels[parm] in atomList:
1041                sigData.append(sigList[colLabels.index(atomList[colLabels[parm]])])
1042            elif colLabels[parm] in cellList:
1043                sigData.append(sigList[colLabels.index(cellList[colLabels[parm]])])
1044            else:
1045                sigData.append(sigList[parm])
1046        return sigData
1047   
1048    def Select(event):
1049        cols = G2frame.dataDisplay.GetSelectedCols()
1050        rows = G2frame.dataDisplay.GetSelectedRows()
1051        if cols:
1052            plotData = []
1053            plotSig = []
1054            plotNames = []
1055            for col in cols:
1056                plotData.append(G2frame.SeqTable.GetColValues(col))
1057                plotSig.append(GetSigData(col))
1058                plotNames.append(G2frame.SeqTable.GetColLabelValue(col))
1059            plotData = np.array(plotData)
1060            G2plt.PlotSeq(G2frame,plotData,plotSig,plotNames,sampleParms)
1061        elif rows:
1062            name = histNames[rows[0]]
1063            G2plt.PlotCovariance(G2frame,Data=data[name])
1064           
1065    def OnSaveSelSeq(event):       
1066        cols = G2frame.dataDisplay.GetSelectedCols()
1067        if cols:
1068            numRows = G2frame.SeqTable.GetNumberRows()
1069            dataNames = []
1070            saveNames = [G2frame.SeqTable.GetRowLabelValue(r) for r in range(numRows)]
1071            saveData = []
1072            for col in cols:
1073                dataNames.append(G2frame.SeqTable.GetColLabelValue(col))
1074                saveData.append(zip(G2frame.SeqTable.GetColValues(col),GetSigData(col)))
1075            lenName = len(saveNames[0])
1076            saveData = np.swapaxes(np.array(saveData),0,1)
1077            dlg = wx.FileDialog(G2frame, 'Choose text output file for your selection', '.', '', 
1078                'Text output file (*.txt)|*.txt',wx.FD_SAVE|wx.FD_OVERWRITE_PROMPT|wx.CHANGE_DIR)
1079            try:
1080                if dlg.ShowModal() == wx.ID_OK:
1081                    SeqTextFile = dlg.GetPath()
1082                    SeqTextFile = G2IO.FileDlgFixExt(dlg,SeqTextFile)
1083                    SeqFile = open(SeqTextFile,'w')
1084                    line = %s  '%('name'.center(lenName))
1085                    for item in dataNames:
1086                        line += ' %12s %12s '%(item.center(12),'esd'.center(12))
1087                    line += '\n'
1088                    SeqFile.write(line)
1089                    for i,item in enumerate(saveData):
1090                        line = " '%s' "%(saveNames[i])
1091                        for val,esd in item:
1092                            line += ' %12.6f %12.6f '%(val,esd)
1093                        line += '\n'
1094                        SeqFile.write(line)
1095                    SeqFile.close()
1096            finally:
1097                dlg.Destroy()
1098           
1099               
1100    if G2frame.dataDisplay:
1101        G2frame.dataDisplay.Destroy()
1102    cellList = {}
1103    newCellDict = data[histNames[0]]['newCellDict']
1104    for item in newCellDict:
1105        if item in data['varyList']:
1106            cellList[newCellDict[item][0]] = item
1107    atomList = {}
1108    newAtomDict = data[histNames[0]]['newAtomDict']
1109    for item in newAtomDict:
1110        if item in data['varyList']:
1111            atomList[newAtomDict[item][0]] = item
1112    sampleParms = GetSampleParms()
1113    Rwps = GetRwps()
1114    G2frame.dataFrame.SetMenuBar(G2frame.dataFrame.SequentialMenu)
1115    G2frame.dataFrame.SetLabel('Sequental refinement results')
1116    G2frame.dataFrame.CreateStatusBar()
1117    G2frame.dataFrame.Bind(wx.EVT_MENU, OnSaveSelSeq, id=wxID_SAVESEQSEL)
1118    colLabels = ['Rwp',]+data['varyList']+atomList.keys()+cellList.keys()
1119    Types = (len(data['varyList']+atomList.keys()+cellList.keys())+1)*[wg.GRID_VALUE_FLOAT,]
1120    seqList = [[Rwps[i],]+list(data[name]['variables']) for i,name in enumerate(histNames)]   
1121    for i,item in enumerate(seqList):
1122        newAtomDict = data[histNames[i]]['newAtomDict']
1123        newCellDict = data[histNames[i]]['newCellDict']
1124        item += [newAtomDict[atomList[parm]][1] for parm in atomList.keys()]
1125        item += [newCellDict[cellList[parm]][1] for parm in cellList.keys()]
1126    G2frame.SeqTable = Table(seqList,colLabels=colLabels,rowLabels=histNames,types=Types)
1127    G2frame.dataDisplay = GSGrid(parent=G2frame.dataFrame)
1128    G2frame.dataDisplay.SetTable(G2frame.SeqTable, True)
1129    G2frame.dataDisplay.EnableEditing(False)
1130    G2frame.dataDisplay.Bind(wg.EVT_GRID_LABEL_LEFT_DCLICK, Select)
1131    G2frame.dataDisplay.SetRowLabelSize(8*len(histNames[0]))       #pretty arbitrary 8
1132    G2frame.dataDisplay.SetMargins(0,0)
1133    G2frame.dataDisplay.AutoSizeColumns(True)
1134    G2frame.dataFrame.setSizePosLeft([700,350])
1135   
1136def UpdateConstraints(G2frame,data):
1137    '''Called when Constraints tree item is selected.
1138    Displays the constraints in the data window
1139    '''
1140    if not data:
1141        data.update({'Hist':[],'HAP':[],'Phase':[]})       #empty dict - fill it
1142    Histograms,Phases = G2frame.GetUsedHistogramsAndPhasesfromTree()
1143    AtomDict = dict([Phases[phase]['pId'],Phases[phase]['Atoms']] for phase in Phases)
1144    Natoms,atomIndx,phaseVary,phaseDict,pawleyLookup,FFtable,BLtable = G2str.GetPhaseData(Phases,Print=False)
1145    phaseList = []
1146    for item in phaseDict:
1147        if item.split(':')[2] not in ['Ax','Ay','Az','Amul','AI/A','Atype','SHorder']:
1148            phaseList.append(item)
1149    phaseList.sort()
1150    phaseAtNames = {}
1151    for item in phaseList:
1152        Split = item.split(':')
1153        if Split[2][:2] in ['AU','Af','dA']:
1154            phaseAtNames[item] = AtomDict[int(Split[0])][int(Split[3])][0]
1155        else:
1156            phaseAtNames[item] = ''
1157           
1158    hapVary,hapDict,controlDict = G2str.GetHistogramPhaseData(Phases,Histograms,Print=False)
1159    hapList = hapDict.keys()
1160    hapList.sort()
1161    histVary,histDict,controlDict = G2str.GetHistogramData(Histograms,Print=False)
1162    histList = []
1163    for item in histDict:
1164        if item.split(':')[2] not in ['Omega','Type','Chi','Phi','Azimuth','Gonio. radius','Lam1','Lam2','Back']:
1165            histList.append(item)
1166    histList.sort()
1167    Indx = {}
1168    scope = {}                          #filled out later
1169    G2frame.Page = [0,'phs']
1170   
1171    def GetPHlegends(Phases,Histograms):
1172        plegend = '\n In p::name'
1173        hlegend = '\n In :h:name'
1174        phlegend = '\n In p:h:name'
1175        for phase in Phases:
1176            plegend += '\n p:: = '+str(Phases[phase]['pId'])+':: for '+phase
1177            count = 0
1178            for histogram in Phases[phase]['Histograms']:
1179                if count < 3:
1180                    phlegend += '\n p:h: = '+str(Phases[phase]['pId'])+':'+str(Histograms[histogram]['hId'])+': for '+phase+' in '+histogram
1181                else:
1182                    phlegend += '\n ... etc.'
1183                    break
1184                count += 1
1185        count = 0
1186        for histogram in Histograms:
1187            if count < 3:
1188                hlegend += '\n :h: = :'+str(Histograms[histogram]['hId'])+': for '+histogram
1189            else:
1190                hlegend += '\n ... etc.'
1191                break
1192            count += 1
1193        return plegend,hlegend,phlegend
1194       
1195    def FindEquivVarb(name,nameList):
1196        outList = []
1197        namelist = [name.split(':')[2],]
1198        if 'dA' in name:
1199            namelist = ['dAx','dAy','dAz']
1200        elif 'AU' in name:
1201            namelist = ['AUiso','AU11','AU22','AU33','AU12','AU13','AU23']
1202        for item in nameList:
1203            key = item.split(':')[2]
1204            if key in namelist and item != name:
1205                outList.append(item)
1206        return outList
1207       
1208    def SelectVarbs(page,FrstVarb,varList,legend,constType):
1209        '''Select variables used in Constraints after one variable has
1210        been selected which determines the appropriate variables to be
1211        used here. Then creates the constraint and adds it to the
1212        constraints list.
1213        Called from OnAddEquivalence, OnAddFunction & OnAddConstraint
1214        '''
1215        #future -  add 'all:all:name', '0:all:name', etc. to the varList
1216        if page[1] == 'phs':
1217            atchoice = [item+' for '+phaseAtNames[item] for item in varList]
1218            dlg = wx.MultiChoiceDialog(G2frame,'Select more variables:'+legend,
1219                'Constrain '+FrstVarb+' and...',atchoice)
1220        else:
1221            dlg = wx.MultiChoiceDialog(G2frame,'Select more variables:'+legend,
1222                'Constrain '+FrstVarb+' and...',varList)
1223        varbs = [FrstVarb,]
1224        if dlg.ShowModal() == wx.ID_OK:
1225            sel = dlg.GetSelections()
1226            for x in sel:
1227                varbs.append(varList[x])
1228        dlg.Destroy()
1229        if len(varbs) > 1:
1230            if 'equivalence' in constType:
1231                constr = [[1.0,FrstVarb]]
1232                for item in varbs[1:]:
1233                    constr += [[1.0,item]]
1234                return [constr+[None,None,'e']]      # list of equivalent variables & mults
1235            elif 'function' in constType:
1236                constr = map(list,zip([1.0 for i in range(len(varbs))],varbs))
1237                return [constr+[None,False,'f']]         #just one constraint
1238            else:       #'constraint'
1239                constr = map(list,zip([1.0 for i in range(len(varbs))],varbs))
1240                return [constr+[1.0,None,'c']]          #just one constraint - default sum to one
1241        return []
1242
1243    def CheckAddedConstraint(newcons):
1244        '''Check a new constraint that has just been input.
1245        If there is an error display a message and give the user a
1246        choice to keep or discard the last entry (why keep? -- they
1247        may want to delete something else or edit multipliers).
1248        Since the varylist is not available, no warning messages
1249        should be generated.
1250        Returns True if constraint should be added
1251        '''
1252        allcons = []
1253        for key in 'Hist','HAP','Phase':
1254            allcons += data[key]
1255        allcons += newcons
1256        if not len(allcons): return True
1257        G2mv.InitVars()   
1258        constDictList,fixedList,ignored = G2str.ProcessConstraints(allcons)
1259        errmsg, warnmsg = G2mv.CheckConstraints('',constDictList,fixedList)
1260        if errmsg:
1261            res = G2frame.ErrorDialog('Constraint Error',
1262                'Error with newly added constraint:\n'+errmsg+
1263                '\n\nDiscard newly added constraint?',parent=G2frame.dataFrame,
1264                wtype=wx.YES_NO)
1265            return res != wx.ID_YES
1266        elif warnmsg:
1267            print 'Unexpected contraint warning:\n',warnmsg
1268        return True
1269
1270    def CheckChangedConstraint():
1271        '''Check all constraints after an edit has been made.
1272        If there is an error display a message and give the user a
1273        choice to keep or discard the last edit.
1274        Since the varylist is not available, no warning messages
1275        should be generated.
1276        Returns True if the edit should be retained
1277        '''
1278        allcons = []
1279        for key in 'Hist','HAP','Phase':
1280            allcons += data[key]
1281        if not len(allcons): return True
1282        G2mv.InitVars()   
1283        constDictList,fixedList,ignored = G2str.ProcessConstraints(allcons)
1284        errmsg, warnmsg = G2mv.CheckConstraints('',constDictList,fixedList)
1285        if errmsg:
1286            res = G2frame.ErrorDialog('Constraint Error',
1287                'Error after editing constraint:\n'+errmsg+
1288                '\n\nDiscard last constraint edit?',parent=G2frame.dataFrame,
1289                wtype=wx.YES_NO)
1290            return res != wx.ID_YES
1291        elif warnmsg:
1292            print 'Unexpected contraint warning:\n',warnmsg
1293        return True
1294             
1295    def OnAddHold(event):
1296        '''add a Hold constraint'''
1297        for phase in Phases:
1298            Phase = Phases[phase]
1299            Atoms = Phase['Atoms']
1300        constr = []
1301        page = G2frame.Page
1302        choice = scope[page[1]]
1303        if page[1] == 'phs':
1304            atchoice = [item+' for '+phaseAtNames[item] for item in choice[2]]
1305            dlg = wx.SingleChoiceDialog(G2frame,'Select 1st variable:'+choice[1],choice[0],atchoice)
1306        else:   
1307            dlg = wx.SingleChoiceDialog(G2frame,'Select 1st variable:'+choice[1],choice[0],choice[2])
1308        if dlg.ShowModal() == wx.ID_OK:
1309            sel = dlg.GetSelection()
1310            FrstVarb = choice[2][sel]
1311            newcons = [[[0.0,FrstVarb],None,None,'h']]
1312            if CheckAddedConstraint(newcons):
1313                data[choice[3]] += newcons
1314        dlg.Destroy()
1315        choice[4]()
1316       
1317    def OnAddEquivalence(event):
1318        '''add an Equivalence constraint'''
1319        constr = []
1320        page = G2frame.Page
1321        choice = scope[page[1]]
1322        if page[1] == 'phs':
1323            atchoice = [item+' for '+phaseAtNames[item] for item in choice[2]]
1324            dlg = wx.SingleChoiceDialog(G2frame,'Select 1st variable:'+choice[1],choice[0],atchoice)
1325        else:   
1326            dlg = wx.SingleChoiceDialog(G2frame,'Select 1st variable:'+choice[1],choice[0],choice[2])
1327        if dlg.ShowModal() == wx.ID_OK:
1328            sel = dlg.GetSelection()
1329            FrstVarb = choice[2][sel]
1330            moreVarb = FindEquivVarb(FrstVarb,choice[2])
1331            newcons = SelectVarbs(page,FrstVarb,moreVarb,choice[1],'equivalence')
1332            if len(newcons) > 0:
1333                if CheckAddedConstraint(newcons):
1334                    data[choice[3]] += newcons
1335        dlg.Destroy()
1336        choice[4]()
1337   
1338    def OnAddFunction(event):
1339        '''add a Function (new variable) constraint'''
1340        constr = []
1341        page = G2frame.Page
1342        choice = scope[page[1]]
1343        if page[1] == 'phs':
1344            atchoice = [item+' for '+phaseAtNames[item] for item in choice[2]]
1345            dlg = wx.SingleChoiceDialog(G2frame,'Select 1st variable:'+choice[1],choice[0],atchoice)
1346        else:   
1347            dlg = wx.SingleChoiceDialog(G2frame,'Select 1st variable:'+choice[1],choice[0],choice[2])
1348        if dlg.ShowModal() == wx.ID_OK:
1349            sel = dlg.GetSelection()
1350            FrstVarb = choice[2][sel]
1351            moreVarb = FindEquivVarb(FrstVarb,choice[2])
1352            newcons = SelectVarbs(page,FrstVarb,moreVarb,choice[1],'function')
1353            if len(newcons) > 0:
1354                if CheckAddedConstraint(newcons):
1355                    data[choice[3]] += newcons
1356        dlg.Destroy()
1357        choice[4]()
1358                       
1359    def OnAddConstraint(event):
1360        '''add a constraint equation to the constraints list'''
1361        constr = []
1362        page = G2frame.Page
1363        choice = scope[page[1]]
1364        if page[1] == 'phs':
1365            atchoice = [item+' for '+phaseAtNames[item] for item in choice[2]]
1366            dlg = wx.SingleChoiceDialog(G2frame,'Select 1st variable:'+choice[1],choice[0],atchoice)
1367        else:   
1368            dlg = wx.SingleChoiceDialog(G2frame,'Select 1st variable:'+choice[1],choice[0],choice[2])
1369        if dlg.ShowModal() == wx.ID_OK:
1370            sel = dlg.GetSelection()
1371            FrstVarb = choice[2][sel]
1372            moreVarb = FindEquivVarb(FrstVarb,choice[2])
1373            newcons = SelectVarbs(page,FrstVarb,moreVarb,choice[1],'constraint')
1374            if len(newcons) > 0:
1375                if CheckAddedConstraint(newcons):
1376                    data[choice[3]] += newcons
1377        dlg.Destroy()
1378        choice[4]()
1379                       
1380    def ConstSizer(name,pageDisplay):
1381        '''This creates a sizer displaying all of the constraints entered
1382        '''
1383        constSizer = wx.FlexGridSizer(1,4,0,0)
1384        maxlen = 70 # characters before wrapping a constraint
1385        for Id,item in enumerate(data[name]):
1386            eqString = ['',]
1387            if item[-1] == 'h':
1388                constSizer.Add((5,5),0)              # blank space for edit button
1389                typeString = ' FIXED   '
1390                eqString[-1] = item[0][1]+'   '
1391            elif isinstance(item[-1],str):
1392                constEdit = wx.Button(pageDisplay,-1,'Edit',style=wx.BU_EXACTFIT)
1393                constEdit.Bind(wx.EVT_BUTTON,OnConstEdit)
1394                constSizer.Add(constEdit)            # edit button
1395                Indx[constEdit.GetId()] = [Id,name]
1396                if item[-1] == 'f':
1397                    for term in item[:-3]:
1398                        if len(eqString[-1]) > maxlen:
1399                            eqString.append(' ')
1400                        m = term[0]
1401                        if eqString[-1] != '':
1402                            if m >= 0:
1403                                eqString[-1] += ' + '
1404                            else:
1405                                eqString[-1] += ' - '
1406                                m = abs(m)
1407                        eqString[-1] += '%.3f*%s '%(m,term[1])
1408                    typeString = ' NEWVAR  '
1409                    eqString[-1] += ' = New Variable   '
1410                elif item[-1] == 'c':
1411                    for term in item[:-3]:
1412                        if len(eqString[-1]) > maxlen:
1413                            eqString.append(' ')
1414                        if eqString[-1] != '':
1415                            if term[0] > 0:
1416                                eqString[-1] += ' + '
1417                            else:
1418                                eqString[-1] += ' - '
1419                        eqString[-1] += '%.3f*%s '%(abs(term[0]),term[1])
1420                    typeString = ' CONSTR  '
1421                    eqString[-1] += ' = %.3f'%(item[-3])+'  '
1422                elif item[-1] == 'e':
1423                    for term in item[:-3]:
1424                        if term[0] == 0: term[0] = 1.0
1425                        if len(eqString[-1]) > maxlen:
1426                            eqString.append(' ')
1427                        if eqString[-1] == '':
1428                            eqString[-1] += '%s '%(term[1])
1429                            first = term[0]
1430                        else:
1431                            eqString[-1] += ' = %.3f*%s '%(first/term[0],term[1])
1432                    typeString = ' EQUIV   '
1433                else:
1434                    print 'Unexpected constraint',item
1435            else:
1436                print 'Removing old-style constraints'
1437                data[name] = []
1438                return constSizer
1439            constDel = wx.Button(pageDisplay,-1,'Delete',style=wx.BU_EXACTFIT)
1440            constDel.Bind(wx.EVT_BUTTON,OnConstDel)
1441            Indx[constDel.GetId()] = [Id,name]
1442            constSizer.Add(constDel)             # delete button
1443            constSizer.Add(wx.StaticText(pageDisplay,-1,typeString),0,wx.ALIGN_CENTER_VERTICAL)
1444            EqSizer = wx.BoxSizer(wx.VERTICAL)
1445            for s in eqString:
1446                EqSizer.Add(wx.StaticText(pageDisplay,-1,s),0,wx.ALIGN_CENTER_VERTICAL)
1447            constSizer.Add(EqSizer,0,wx.ALIGN_CENTER_VERTICAL)
1448            # if item[-1] == 'f':
1449            #     constRef = wx.CheckBox(pageDisplay,-1,label=' Refine?')
1450            #     constRef.SetValue(item[-2])
1451            #     constRef.Bind(wx.EVT_CHECKBOX,OnConstRef)
1452            #     Indx[constRef.GetId()] = item
1453            #     constSizer.Add(constRef)
1454            # else:
1455            #     constSizer.Add((5,5),0)
1456        return constSizer
1457               
1458    # def OnConstRef(event):
1459    #     Obj = event.GetEventObject()
1460    #     Indx[Obj.GetId()][-2] = Obj.GetValue()
1461       
1462    def OnConstDel(event):
1463        Obj = event.GetEventObject()
1464        Id,name = Indx[Obj.GetId()]
1465        del(data[name][Id])
1466        OnPageChanged(None)       
1467       
1468    def OnConstEdit(event):
1469        '''Called to edit an individual contraint by the Edit button'''
1470        Obj = event.GetEventObject()
1471        Id,name = Indx[Obj.GetId()]
1472        sep = '*'
1473        if data[name][Id][-1] == 'f':
1474            items = data[name][Id][:-3]+[[],]
1475            constType = 'New Variable'
1476            lbl = 'Enter value for each term in constraint; sum = new variable'
1477        elif data[name][Id][-1] == 'c':
1478            items = data[name][Id][:-3]+[
1479                [data[name][Id][-3],'fixed value ='],[]]
1480            constType = 'Constraint'
1481            lbl = 'Edit value for each term in constant constraint sum'
1482        elif data[name][Id][-1] == 'e':
1483            items = data[name][Id][:-3]+[[],]
1484            constType = 'Equivalence'
1485            lbl = 'The following terms are set to be equal:'
1486            sep = '/'
1487        else:
1488            return
1489        dlg = G2frame.ConstraintDialog(G2frame.dataFrame,constType,lbl,items,sep)
1490        try:
1491            if dlg.ShowModal() == wx.ID_OK:
1492                prev = data[name][Id]
1493                result = dlg.GetData()
1494                if data[name][Id][-1] == 'c':
1495                    data[name][Id][:-3] = result[:-2]
1496                    data[name][Id][-3] = result[-2][0]
1497                else:
1498                    data[name][Id][:-3] = result[:-1]
1499                if not CheckChangedConstraint():
1500                    data[name][Id] = prev
1501        except:
1502            import traceback
1503            print traceback.format_exc()
1504        finally:
1505            dlg.Destroy()           
1506        OnPageChanged(None)                     
1507   
1508    def UpdateHAPConstr():
1509        '''Responds to press on Histogram/Phase Constraints tab,
1510        shows constraints in data window'''
1511        HAPConstr.DestroyChildren()
1512        HAPDisplay = wx.Panel(HAPConstr)
1513        HAPSizer = wx.BoxSizer(wx.VERTICAL)
1514        HAPSizer.Add((5,5),0)
1515        HAPSizer.Add(ConstSizer('HAP',HAPDisplay))
1516        HAPDisplay.SetSizer(HAPSizer,True)
1517        Size = HAPSizer.GetMinSize()
1518        Size[0] += 40
1519        Size[1] = max(Size[1],250) + 20
1520        HAPDisplay.SetSize(Size)
1521        # scroll bar not working, at least not on Mac
1522        HAPConstr.SetScrollbars(10,10,Size[0]/10-4,Size[1]/10-1)
1523        Size[1] = min(Size[1],250)
1524        G2frame.dataFrame.setSizePosLeft(Size)
1525       
1526    def UpdateHistConstr():
1527        '''Responds to press on Histogram Constraints tab,
1528        shows constraints in data window'''
1529        HistConstr.DestroyChildren()
1530        HistDisplay = wx.Panel(HistConstr)
1531        HistSizer = wx.BoxSizer(wx.VERTICAL)
1532        HistSizer.Add((5,5),0)       
1533        HistSizer.Add(ConstSizer('Hist',HistDisplay))
1534        HistDisplay.SetSizer(HistSizer,True)
1535        Size = HistSizer.GetMinSize()
1536        Size[0] += 40
1537        Size[1] = max(Size[1],250) + 20
1538        HistDisplay.SetSize(Size)
1539        HistConstr.SetScrollbars(10,10,Size[0]/10-4,Size[1]/10-1)
1540        Size[1] = min(Size[1],250)
1541        G2frame.dataFrame.setSizePosLeft(Size)
1542       
1543    def UpdatePhaseConstr():
1544        '''Responds to press on Phase Constraint tab,
1545        shows constraints in data window'''
1546        PhaseConstr.DestroyChildren()
1547        PhaseDisplay = wx.Panel(PhaseConstr)
1548        PhaseSizer = wx.BoxSizer(wx.VERTICAL)
1549        PhaseSizer.Add((5,5),0)       
1550        PhaseSizer.Add(ConstSizer('Phase',PhaseDisplay))
1551        PhaseDisplay.SetSizer(PhaseSizer,True)
1552        Size = PhaseSizer.GetMinSize()
1553        Size[0] += 40
1554        Size[1] = max(Size[1],250) + 20
1555        PhaseDisplay.SetSize(Size)
1556        PhaseConstr.SetScrollbars(10,10,Size[0]/10-4,Size[1]/10-1)
1557        Size[1] = min(Size[1],250)
1558        G2frame.dataFrame.setSizePosLeft(Size)
1559   
1560    def OnPageChanged(event):
1561        if event:       #page change event!
1562            page = event.GetSelection()
1563        else:
1564            page = G2frame.dataDisplay.GetSelection()
1565        oldPage = G2frame.dataDisplay.ChangeSelection(page)
1566        text = G2frame.dataDisplay.GetPageText(page)
1567        if text == 'Histogram/Phase constraints':
1568            G2frame.Page = [page,'hap']
1569            UpdateHAPConstr()
1570        elif text == 'Histogram constraints':
1571            G2frame.Page = [page,'hst']
1572            UpdateHistConstr()
1573        elif text == 'Phase constraints':
1574            G2frame.Page = [page,'phs']
1575            UpdatePhaseConstr()
1576
1577    def SetStatusLine(text):
1578        Status.SetStatusText(text)                                     
1579       
1580    plegend,hlegend,phlegend = GetPHlegends(Phases,Histograms)
1581    scope = {'hst':['Histogram contraints:',hlegend,histList,'Hist',UpdateHistConstr],
1582        'hap':['Histogram * Phase contraints:',phlegend,hapList,'HAP',UpdateHAPConstr],
1583        'phs':['Phase contraints:',plegend,phaseList,'Phase',UpdatePhaseConstr]}
1584    if G2frame.dataDisplay:
1585        G2frame.dataDisplay.Destroy()
1586    G2frame.dataFrame.SetMenuBar(G2frame.dataFrame.ConstraintMenu)
1587    G2frame.dataFrame.SetLabel('Constraints')
1588    if not G2frame.dataFrame.GetStatusBar():
1589        Status = G2frame.dataFrame.CreateStatusBar()
1590    SetStatusLine('')
1591   
1592    G2frame.dataFrame.SetMenuBar(G2frame.dataFrame.ConstraintMenu)
1593    G2frame.dataFrame.Bind(wx.EVT_MENU, OnAddConstraint, id=wxID_CONSTRAINTADD)
1594    G2frame.dataFrame.Bind(wx.EVT_MENU, OnAddFunction, id=wxID_FUNCTADD)
1595    G2frame.dataFrame.Bind(wx.EVT_MENU, OnAddEquivalence, id=wxID_EQUIVADD)
1596    G2frame.dataFrame.Bind(wx.EVT_MENU, OnAddHold, id=wxID_HOLDADD)
1597    G2frame.dataDisplay = GSNoteBook(parent=G2frame.dataFrame,size=G2frame.dataFrame.GetClientSize())
1598   
1599    PhaseConstr = wx.ScrolledWindow(G2frame.dataDisplay)
1600    G2frame.dataDisplay.AddPage(PhaseConstr,'Phase constraints')
1601    HAPConstr = wx.ScrolledWindow(G2frame.dataDisplay)
1602    G2frame.dataDisplay.AddPage(HAPConstr,'Histogram/Phase constraints')
1603    HistConstr = wx.ScrolledWindow(G2frame.dataDisplay)
1604    G2frame.dataDisplay.AddPage(HistConstr,'Histogram constraints')
1605    UpdatePhaseConstr()
1606
1607    G2frame.dataDisplay.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGED, OnPageChanged)
1608    # validate all the constrants -- should not see any errors here normally
1609    allcons = []
1610    for key in 'Hist','HAP','Phase':
1611        allcons += data[key]
1612    if not len(allcons): return
1613    G2mv.InitVars()   
1614    constDictList,fixedList,ignored = G2str.ProcessConstraints(allcons)
1615    errmsg, warnmsg = G2mv.CheckConstraints('',constDictList,fixedList)
1616    if errmsg:
1617        G2frame.ErrorDialog('Constraint Error','Error in constraints:\n'+errmsg,
1618            parent=G2frame.dataFrame)
1619    elif warnmsg:
1620        print 'Unexpected contraint warning:\n',warnmsg
1621       
1622def UpdateRestraints(G2frame,data,Phases,phaseName):
1623    if not len(Phases):
1624        print 'There are no phases to form restraints'
1625        return
1626    phasedata = Phases[phaseName]
1627    if phaseName not in data:
1628        data[phaseName] = {}
1629    restrData = data[phaseName]
1630    if 'Bond' not in restrData:
1631        restrData['Bond'] = {'wtFactor':1.0,'Bonds':[],'Use':True}
1632    if 'Angle' not in restrData:
1633        restrData['Angle'] = {'wtFactor':1.0,'Angles':[],'Use':True}
1634    if 'Plane' not in restrData:
1635        restrData['Plane'] = {'wtFactor':1.0,'Planes':[],'Use':True}
1636    if 'Chiral' not in restrData:
1637        restrData['Chiral'] = {'wtFactor':1.0,'Volumes':[],'Use':True}
1638   
1639    def OnSelectPhase(event):
1640        dlg = wx.SingleChoiceDialog(G2frame,'Select','Phase',Phases.keys())
1641        try:
1642            if dlg.ShowModal() == wx.ID_OK:
1643                phaseName = Phases.keys()[dlg.GetSelection()]
1644                UpdateRestraints(G2frame,data,Phases,phaseName)
1645        finally:
1646            dlg.Destroy()
1647   
1648    def OnAddRestraint(event):
1649        page = G2frame.dataDisplay.GetSelection()
1650        if 'Bond' in G2frame.dataDisplay.GetPageText(page):
1651            AddBondRestraint()
1652        elif 'Angle' in G2frame.dataDisplay.GetPageText(page):
1653            AddAngleRestraint()
1654        elif 'Plane' in G2frame.dataDisplay.GetPageText(page):
1655            AddPlaneRestraint()
1656        elif 'Chiral' in G2frame.dataDisplay.GetPageText(page):
1657            AddChiralRestraint()
1658           
1659    def AddBondRestraint():
1660        print 'Bond restraint'
1661
1662    def AddAngleRestraint():
1663        print 'Angle restraint'
1664
1665    def AddPlaneRestraint():
1666        print 'Plane restraint'
1667
1668    def AddChiralRestraint():
1669        print 'Chiral restraint'
1670       
1671    def WtBox(wind,restData):
1672       
1673        def OnWtFactor(event):
1674            try:
1675                value = float(wtfactor.GetValue())
1676            except ValueError:
1677                value = 1.0
1678            restData['wtFactor'] = value
1679            wtfactor.SetValue('%.2f'%(value))
1680           
1681        def OnUseData(event):
1682            restData['Use'] = Obj.GetValue()
1683
1684        wtBox = wx.BoxSizer(wx.HORIZONTAL)
1685        wtBox.Add(wx.StaticText(wind,-1,'Restraint weight factor:'),0,wx.ALIGN_CENTER_VERTICAL)
1686        wtfactor = wx.TextCtrl(wind,-1,value='%.2f'%(restData['wtFactor']),style=wx.TE_PROCESS_ENTER)
1687        wtfactor.Bind(wx.EVT_TEXT_ENTER,OnWtFactor)
1688        wtfactor.Bind(wx.EVT_KILL_FOCUS,OnWtFactor)
1689        wtBox.Add(wtfactor,0,wx.ALIGN_CENTER_VERTICAL)
1690        useData = wx.CheckBox(wind,-1,label=' Use?')
1691        useData.Bind(wx.EVT_CHECKBOX, OnUseData)
1692        useData.SetValue(restData['Use'])       
1693        wtBox.Add(useData,0,wx.ALIGN_CENTER_VERTICAL)
1694        return wtBox
1695       
1696    def UpdateBondRestr(bondRestData):
1697       
1698        def ChangeCell(event):
1699            r,c =  event.GetRow(),event.GetCol()
1700            if r >= 0 and c >= 0:
1701                bondList[r][c+2] = table[r][c]
1702               
1703        def OnDeleteRestraint(event):
1704            rows = Bonds.GetSelectedRows()
1705            Bonds.ClearSelection()
1706            rows.sort()
1707            rows.reverse()
1708            for row in rows:
1709                bondList.remove(bondList[row])
1710            UpdateBondRestr(bondRestData)               
1711           
1712        BondRestr.DestroyChildren()
1713        dataDisplay = wx.Panel(BondRestr)
1714        mainSizer = wx.BoxSizer(wx.VERTICAL)
1715        mainSizer.Add((5,5),0)
1716        mainSizer.Add(WtBox(BondRestr,bondRestData),0,wx.ALIGN_CENTER_VERTICAL)
1717
1718        bondList = bondRestData['Bonds']
1719        if len(bondList):
1720            table = []
1721            rowLabels = []
1722            colLabels = ['A+SymOp  B+SymOp','d-calc','d-obs','esd']
1723            Types = [wg.GRID_VALUE_STRING,]+3*[wg.GRID_VALUE_FLOAT+':10,3',]
1724            for i,[atoms,ops,indx,dcalc,dobs,esd] in enumerate(bondList):
1725                table.append([atoms[0]+'+ ('+ops[0]+')  '+atoms[1]+'+ ('+ops[1]+')',dcalc,dobs,esd])
1726                rowLabels.append(str(i))
1727            bondTable = Table(table,rowLabels=rowLabels,colLabels=colLabels,types=Types)
1728            Bonds = GSGrid(BondRestr)
1729            Bonds.SetTable(bondTable, True)
1730            Bonds.AutoSizeColumns(False)
1731            for r in range(len(bondList)):
1732                for c in range(2):
1733                    Bonds.SetReadOnly(r,c,True)
1734                    Bonds.SetCellStyle(r,c,VERY_LIGHT_GREY,True)
1735            Bonds.Bind(wg.EVT_GRID_CELL_CHANGE, ChangeCell)
1736            G2frame.dataFrame.Bind(wx.EVT_MENU, OnDeleteRestraint, id=wxID_RESTDELETE)
1737            mainSizer.Add(Bonds,0,)
1738        else:
1739            mainSizer.Add(wx.StaticText(BondRestr,-1,'No bond distance restraints for this phase'),0,)
1740
1741        BondRestr.SetSizer(mainSizer)
1742        Size = mainSizer.Fit(G2frame.dataFrame)
1743        Size[0] += 5
1744        Size[1] += 25       #make room for tab
1745        BondRestr.SetSize(Size)
1746        G2frame.dataFrame.setSizePosLeft(Size)
1747       
1748    def UpdateAngleRestr(angleRestData):
1749
1750        def ChangeCell(event):
1751            r,c =  event.GetRow(),event.GetCol()
1752            if r >= 0 and c >= 0:
1753                angleList[r][c+2] = table[r][c]
1754           
1755        def OnDeleteRestraint(event):
1756            rows = Angles.GetSelectedRows()
1757            rows.sort()
1758            rows.reverse()
1759            for row in rows:
1760                angleList.remove(angleList[row])
1761            UpdateAngleRestr(angleRestData)               
1762           
1763        AngleRestr.DestroyChildren()
1764        dataDisplay = wx.Panel(AngleRestr)
1765        mainSizer = wx.BoxSizer(wx.VERTICAL)
1766        mainSizer.Add((5,5),0)
1767        mainSizer.Add(WtBox(AngleRestr,angleRestData),0,wx.ALIGN_CENTER_VERTICAL)
1768
1769        angleList = angleRestData['Angles']
1770        if len(angleList):
1771            table = []
1772            rowLabels = []
1773            colLabels = ['A+SymOp  B+SymOp  C+SymOp','calc','obs','esd']
1774            Types = [wg.GRID_VALUE_STRING,]+3*[wg.GRID_VALUE_FLOAT+':10,2',]
1775            for i,[atoms,ops,indx,dcalc,dobs,esd] in enumerate(angleList):
1776                table.append([atoms[0]+'+ ('+ops[0]+')  '+atoms[1]+'+ ('+ops[1]+')  '+atoms[2]+ \
1777                '+ ('+ops[2]+')',dcalc,dobs,esd])
1778                rowLabels.append(str(i))
1779            angleTable = Table(table,rowLabels=rowLabels,colLabels=colLabels,types=Types)
1780            Angles = GSGrid(AngleRestr)
1781            Angles.SetTable(angleTable, True)
1782            Angles.AutoSizeColumns(False)
1783            for r in range(len(angleList)):
1784                for c in range(2):
1785                    Angles.SetReadOnly(r,c,True)
1786                    Angles.SetCellStyle(r,c,VERY_LIGHT_GREY,True)
1787            Angles.Bind(wg.EVT_GRID_CELL_CHANGE, ChangeCell)
1788            G2frame.dataFrame.Bind(wx.EVT_MENU, OnDeleteRestraint, id=wxID_RESTDELETE)
1789            mainSizer.Add(Angles,0,)
1790        else:
1791            mainSizer.Add(wx.StaticText(AngleRestr,-1,'No bond angle restraints for this phase'),0,)
1792
1793        AngleRestr.SetSizer(mainSizer)
1794        Size = mainSizer.Fit(G2frame.dataFrame)
1795        Size[0] += 5
1796        Size[1] += 25       #make room for tab
1797        AngleRestr.SetSize(Size)
1798        G2frame.dataFrame.setSizePosLeft(Size)
1799   
1800    def UpdatePlaneRestr(planeRestData):
1801
1802        def ChangeCell(event):
1803            r,c =  event.GetRow(),event.GetCol()
1804            if r >= 0 and c >= 0:
1805                planeList[r][c+2] = table[r][c]
1806           
1807        def OnDeleteRestraint(event):
1808            rows = Planes.GetSelectedRows()
1809            rows.sort()
1810            rows.reverse()
1811            for row in rows:
1812                planeList.remove(planeList[row])
1813            UpdatePlaneRestr(planeRestData)               
1814           
1815        PlaneRestr.DestroyChildren()
1816        dataDisplay = wx.Panel(PlaneRestr)
1817        mainSizer = wx.BoxSizer(wx.VERTICAL)
1818        mainSizer.Add((5,5),0)
1819        mainSizer.Add(WtBox(PlaneRestr,planeRestData),0,wx.ALIGN_CENTER_VERTICAL)
1820
1821        planeList = planeRestData['Planes']
1822        if len(planeList):
1823            table = []
1824            rowLabels = []
1825            colLabels = ['atom+SymOp','calc','obs','esd']
1826            Types = [wg.GRID_VALUE_STRING,]+3*[wg.GRID_VALUE_FLOAT+':10,2',]
1827            for i,[atoms,ops,indx,dcalc,dobs,esd] in enumerate(planeList):
1828                atString = ''
1829                for a,atom in enumerate(atoms):
1830                    atString += atom+'+ ('+ops[a]+'),'
1831                    if (a+1)%3 == 0:
1832                        atString += '\n'
1833                table.append([atString[:-1],dcalc,dobs,esd])
1834                rowLabels.append(str(i))
1835            planeTable = Table(table,rowLabels=rowLabels,colLabels=colLabels,types=Types)
1836            Planes = GSGrid(PlaneRestr)
1837            Planes.SetTable(planeTable, True)
1838            Planes.AutoSizeColumns(False)
1839            Planes.AutoSizeRows(False)
1840            for r in range(len(planeList)):
1841                for c in range(3):
1842                    Planes.SetReadOnly(r,c,True)
1843                    Planes.SetCellStyle(r,c,VERY_LIGHT_GREY,True)
1844            Planes.Bind(wg.EVT_GRID_CELL_CHANGE, ChangeCell)
1845            G2frame.dataFrame.Bind(wx.EVT_MENU, OnDeleteRestraint, id=wxID_RESTDELETE)
1846            mainSizer.Add(Planes,0,)
1847        else:
1848            mainSizer.Add(wx.StaticText(PlaneRestr,-1,'No plane restraints for this phase'),0,)
1849
1850        PlaneRestr.SetSizer(mainSizer)
1851        Size = mainSizer.Fit(G2frame.dataFrame)
1852        Size[0] += 5
1853        Size[1] += 25       #make room for tab
1854        PlaneRestr.SetSize(Size)
1855        G2frame.dataFrame.setSizePosLeft(Size)
1856   
1857    def UpdateChiralRestr(chiralRestData):
1858
1859        def ChangeCell(event):
1860            r,c =  event.GetRow(),event.GetCol()
1861            if r >= 0 and c >= 0:
1862                volumeList[r][c+2] = table[r][c]
1863           
1864        def OnDeleteRestraint(event):
1865            rows = Volumes.GetSelectedRows()
1866            rows.sort()
1867            rows.reverse()
1868            for row in rows:
1869                volumeList.remove(volumeList[row])
1870            UpdateChiralRestr(chiralRestData)               
1871           
1872        ChiralRestr.DestroyChildren()
1873        dataDisplay = wx.Panel(ChiralRestr)
1874        mainSizer = wx.BoxSizer(wx.VERTICAL)
1875        mainSizer.Add((5,5),0)
1876        mainSizer.Add(WtBox(ChiralRestr,chiralRestData),0,wx.ALIGN_CENTER_VERTICAL)
1877
1878        volumeList = chiralRestData['Volumes']
1879        if len(volumeList):
1880            table = []
1881            rowLabels = []
1882            colLabels = ['O+SymOp  A+SymOp  B+SymOp  C+SymOp','calc','obs','esd']
1883            Types = [wg.GRID_VALUE_STRING,]+3*[wg.GRID_VALUE_FLOAT+':10,2',]
1884            for i,[atoms,ops,indx,dcalc,dobs,esd] in enumerate(volumeList):
1885                table.append([atoms[0]+'+ ('+ops[0]+') '+atoms[1]+'+ ('+ops[1]+') '+atoms[2]+ \
1886                '+ ('+ops[2]+') '+atoms[3]+'+ ('+ops[3]+')',dcalc,dobs,esd])
1887                rowLabels.append(str(i))
1888            volumeTable = Table(table,rowLabels=rowLabels,colLabels=colLabels,types=Types)
1889            Volumes = GSGrid(ChiralRestr)
1890            Volumes.SetTable(volumeTable, True)
1891            Volumes.AutoSizeColumns(False)
1892            for r in range(len(volumeList)):
1893                for c in range(2):
1894                    Volumes.SetReadOnly(r,c,True)
1895                    Volumes.SetCellStyle(r,c,VERY_LIGHT_GREY,True)
1896            Volumes.Bind(wg.EVT_GRID_CELL_CHANGE, ChangeCell)
1897            G2frame.dataFrame.Bind(wx.EVT_MENU, OnDeleteRestraint, id=wxID_RESTDELETE)
1898            mainSizer.Add(Volumes,0,)
1899        else:
1900            mainSizer.Add(wx.StaticText(ChiralRestr,-1,'No chiral volume restraints for this phase'),0,)
1901
1902        ChiralRestr.SetSizer(mainSizer)
1903        Size = mainSizer.Fit(G2frame.dataFrame)
1904        Size[0] += 5
1905        Size[1] += 25       #make room for tab
1906        ChiralRestr.SetSize(Size)
1907        G2frame.dataFrame.setSizePosLeft(Size)
1908   
1909    def OnPageChanged(event):
1910        page = event.GetSelection()
1911        text = G2frame.dataDisplay.GetPageText(page)
1912        if text == 'Bond restraints':
1913            G2frame.dataFrame.SetMenuBar(G2frame.dataFrame.RestraintMenu)
1914            bondRestData = restrData['Bond']
1915            UpdateBondRestr(bondRestData)
1916        elif text == 'Angle restraints':
1917            G2frame.dataFrame.SetMenuBar(G2frame.dataFrame.RestraintMenu)
1918            angleRestData = restrData['Angle']
1919            UpdateAngleRestr(angleRestData)
1920        elif text == 'Plane restraints':
1921            G2frame.dataFrame.SetMenuBar(G2frame.dataFrame.RestraintMenu)
1922            planeRestData = restrData['Plane']
1923            UpdatePlaneRestr(planeRestData)
1924        elif text == 'Chiral restraints':
1925            G2frame.dataFrame.SetMenuBar(G2frame.dataFrame.RestraintMenu)
1926            chiralRestData = restrData['Chiral']
1927            UpdateChiralRestr(chiralRestData)
1928        event.Skip()
1929
1930    if G2frame.dataDisplay:
1931        G2frame.dataDisplay.Destroy()
1932       
1933    G2frame.dataFrame.SetMenuBar(G2frame.dataFrame.RestraintMenu)
1934    G2frame.dataFrame.SetLabel('restraints for '+phaseName)
1935    G2frame.dataFrame.RestraintEdit.Enable(wxID_RESTSELPHASE,False)
1936    if len(Phases) > 1:
1937        G2frame.dataFrame.RestraintEdit.Enable(wxID_RESTSELPHASE,True)
1938        G2frame.dataFrame.Bind(wx.EVT_MENU, OnSelectPhase, id=wxID_RESTSELPHASE)
1939    G2frame.dataFrame.Bind(wx.EVT_MENU, OnAddRestraint, id=wxID_RESTRAINTADD)
1940    G2frame.dataDisplay = GSNoteBook(parent=G2frame.dataFrame,size=G2frame.dataFrame.GetClientSize())
1941   
1942    BondRestr = wx.ScrolledWindow(G2frame.dataDisplay)
1943    G2frame.dataDisplay.AddPage(BondRestr,'Bond restraints')
1944    AngleRestr = wx.ScrolledWindow(G2frame.dataDisplay)
1945    G2frame.dataDisplay.AddPage(AngleRestr,'Angle restraints')
1946    PlaneRestr = wx.ScrolledWindow(G2frame.dataDisplay)
1947    G2frame.dataDisplay.AddPage(PlaneRestr,'Plane restraints')
1948    ChiralRestr = wx.ScrolledWindow(G2frame.dataDisplay)
1949    G2frame.dataDisplay.AddPage(ChiralRestr,'Chiral restraints')
1950    UpdateBondRestr(restrData['Bond'])
1951
1952    G2frame.dataDisplay.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGED, OnPageChanged)
1953   
1954def UpdatePWHKPlot(G2frame,kind,item):
1955
1956    def OnErrorAnalysis(event):
1957        G2plt.PlotDeltSig(G2frame,kind)
1958       
1959    def OnWtFactor(event):
1960        try:
1961            val = float(wtval.GetValue())
1962        except ValueError:
1963            val = data[0]['wtFactor']
1964        data[0]['wtFactor'] = val
1965        wtval.SetValue('%.3f'%(val))
1966           
1967    data = G2frame.PatternTree.GetItemPyData(item)
1968    if 'wtFactor' not in data[0]:
1969        data[0] = {'wtFactor':1.0}
1970    if G2frame.dataDisplay:
1971        G2frame.dataDisplay.Destroy()
1972    G2frame.dataFrame.SetMenuBar(G2frame.dataFrame.ErrorMenu)
1973    G2frame.dataFrame.Bind(wx.EVT_MENU,OnErrorAnalysis, id=wxID_PWDANALYSIS)
1974    G2frame.dataDisplay = wx.Panel(G2frame.dataFrame)
1975   
1976    mainSizer = wx.BoxSizer(wx.VERTICAL)
1977    mainSizer.Add((5,5),)
1978    wtSizer = wx.BoxSizer(wx.HORIZONTAL)
1979    wtSizer.Add(wx.StaticText(G2frame.dataDisplay,-1,' Weight factor: '),0,wx.ALIGN_CENTER_VERTICAL)
1980    wtval = wx.TextCtrl(G2frame.dataDisplay,-1,'%.3f'%(data[0]['wtFactor']),style=wx.TE_PROCESS_ENTER)
1981    wtval.Bind(wx.EVT_TEXT_ENTER,OnWtFactor)
1982    wtval.Bind(wx.EVT_KILL_FOCUS,OnWtFactor)
1983    wtSizer.Add(wtval,0,wx.ALIGN_CENTER_VERTICAL)
1984    mainSizer.Add(wtSizer)
1985    mainSizer.Layout()   
1986    G2frame.dataDisplay.SetSizer(mainSizer)
1987    G2frame.dataFrame.setSizePosLeft(mainSizer.Fit(G2frame.dataFrame))
1988    G2frame.PatternTree.SetItemPyData(item,data)
1989    if kind == 'PWDR':
1990        G2plt.PlotPatterns(G2frame,newPlot=True)
1991    elif kind == 'HKLF':
1992        G2plt.PlotSngl(G2frame,newPlot=True)
1993                 
1994def UpdateHKLControls(G2frame,data):
1995   
1996    def OnScaleSlider(event):
1997        scale = int(scaleSel.GetValue())/1000.
1998        scaleSel.SetValue(int(scale*1000.))
1999        data['Scale'] = scale*10.
2000        G2plt.PlotSngl(G2frame)
2001       
2002    def OnLayerSlider(event):
2003        layer = layerSel.GetValue()
2004        data['Layer'] = layer
2005        G2plt.PlotSngl(G2frame)
2006       
2007    def OnSelZone(event):
2008        data['Zone'] = zoneSel.GetValue()
2009        izone = zones.index(data['Zone'])
2010        layerSel.SetRange(maxValue=HKLmax[izone],minValue=HKLmin[izone])
2011        G2plt.PlotSngl(G2frame,newPlot=True)
2012       
2013    def OnSelType(event):
2014        data['Type'] = typeSel.GetValue()
2015        G2plt.PlotSngl(G2frame)
2016       
2017    def SetStatusLine():
2018        Status.SetStatusText("")
2019                                     
2020    if G2frame.dataDisplay:
2021        G2frame.dataDisplay.Destroy()
2022    if not G2frame.dataFrame.GetStatusBar():
2023        Status = G2frame.dataFrame.CreateStatusBar()
2024    SetStatusLine()
2025    zones = ['100','010','001']
2026    HKLmax = data['HKLmax']
2027    HKLmin = data['HKLmin']
2028    if data['ifFc']:
2029        typeChoices = ['Fosq','Fo','|DFsq|/sig','|DFsq|>sig','|DFsq|>3sig']
2030    else:
2031        typeChoices = ['Fosq','Fo']
2032    G2frame.dataDisplay = wx.Panel(G2frame.dataFrame)
2033    G2frame.dataFrame.SetMenuBar(G2frame.dataFrame.BlankMenu)
2034    G2frame.dataFrame.SetTitle('HKL Plot Controls')
2035    mainSizer = wx.BoxSizer(wx.VERTICAL)
2036    mainSizer.Add((5,10),0)
2037   
2038    scaleSizer = wx.BoxSizer(wx.HORIZONTAL)
2039    scaleSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' Scale'),0,
2040        wx.ALIGN_CENTER_VERTICAL|wx.EXPAND)
2041    scaleSel = wx.Slider(parent=G2frame.dataDisplay,maxValue=1000,minValue=1,
2042        style=wx.SL_HORIZONTAL,value=int(data['Scale']*100))
2043    scaleSizer.Add(scaleSel,1,wx.EXPAND|wx.RIGHT|wx.ALIGN_CENTER_VERTICAL)
2044    scaleSel.SetLineSize(10)
2045    scaleSel.SetPageSize(10)
2046    scaleSel.Bind(wx.EVT_SLIDER, OnScaleSlider)
2047    mainSizer.Add(scaleSizer,0,wx.EXPAND|wx.RIGHT)
2048    mainSizer.Add((0,10),0)   
2049   
2050    zoneSizer = wx.BoxSizer(wx.HORIZONTAL)
2051    zoneSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' Zone  '),0,
2052        wx.ALIGN_CENTER_VERTICAL)
2053    zoneSel = wx.ComboBox(parent=G2frame.dataDisplay,value=data['Zone'],choices=['100','010','001'],
2054        style=wx.CB_READONLY|wx.CB_DROPDOWN)
2055    zoneSel.Bind(wx.EVT_COMBOBOX, OnSelZone)
2056    zoneSizer.Add(zoneSel,0,wx.ALIGN_CENTER_VERTICAL)
2057    zoneSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' Plot type  '),0,
2058        wx.ALIGN_CENTER_VERTICAL)       
2059    typeSel = wx.ComboBox(parent=G2frame.dataDisplay,value=data['Type'],choices=typeChoices,
2060        style=wx.CB_READONLY|wx.CB_DROPDOWN)
2061    typeSel.Bind(wx.EVT_COMBOBOX, OnSelType)
2062    zoneSizer.Add(typeSel,0,wx.ALIGN_CENTER_VERTICAL)
2063    zoneSizer.Add((10,0),0)   
2064    mainSizer.Add(zoneSizer,0,wx.EXPAND|wx.RIGHT)
2065    mainSizer.Add((0,10),0)   
2066       
2067    izone = zones.index(data['Zone'])
2068    layerSizer = wx.BoxSizer(wx.HORIZONTAL)
2069    layerSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' Layer'),0,
2070        wx.ALIGN_CENTER_VERTICAL|wx.EXPAND)
2071    layerSel = wx.Slider(parent=G2frame.dataDisplay,maxValue=HKLmax[izone],minValue=HKLmin[izone],
2072        style=wx.SL_HORIZONTAL|wx.SL_AUTOTICKS|wx.SL_LABELS,value=0)
2073    layerSel.SetLineSize(1)
2074    layerSel.SetPageSize(1)
2075    layerSel.Bind(wx.EVT_SLIDER, OnLayerSlider)   
2076    layerSizer.Add(layerSel,1,wx.EXPAND|wx.RIGHT|wx.ALIGN_CENTER_VERTICAL)
2077    layerSizer.Add((10,0),0)   
2078    mainSizer.Add(layerSizer,1,wx.EXPAND|wx.RIGHT)
2079
2080       
2081    mainSizer.Layout()   
2082    G2frame.dataDisplay.SetSizer(mainSizer)
2083    G2frame.dataDisplay.SetSize(mainSizer.Fit(G2frame.dataFrame))
2084    G2frame.dataFrame.setSizePosLeft(mainSizer.Fit(G2frame.dataFrame))
2085
2086def GetPatternTreeDataNames(G2frame,dataTypes):
2087    names = []
2088    item, cookie = G2frame.PatternTree.GetFirstChild(G2frame.root)       
2089    while item:
2090        name = G2frame.PatternTree.GetItemText(item)
2091        if name[:4] in dataTypes:
2092            names.append(name)
2093        item, cookie = G2frame.PatternTree.GetNextChild(G2frame.root, cookie)
2094    return names
2095                         
2096def GetPatternTreeItemId(G2frame, parentId, itemText):
2097    item, cookie = G2frame.PatternTree.GetFirstChild(parentId)
2098    while item:
2099        if G2frame.PatternTree.GetItemText(item) == itemText:
2100            return item
2101        item, cookie = G2frame.PatternTree.GetNextChild(parentId, cookie)
2102    return 0               
2103
2104def MovePatternTreeToGrid(G2frame,item):
2105   
2106#    print G2frame.PatternTree.GetItemText(item)
2107   
2108    oldPage = 0
2109    if G2frame.dataFrame:
2110        G2frame.dataFrame.SetMenuBar(G2frame.dataFrame.BlankMenu)
2111        if G2frame.dataFrame.GetLabel() == 'Comments':
2112            data = [G2frame.dataDisplay.GetValue()]
2113            G2frame.dataDisplay.Clear() 
2114            Id = GetPatternTreeItemId(G2frame,G2frame.root, 'Comments')
2115            if Id: G2frame.PatternTree.SetItemPyData(Id,data)
2116        elif G2frame.dataFrame.GetLabel() == 'Notebook':
2117            data = [G2frame.dataDisplay.GetValue()]
2118            G2frame.dataDisplay.Clear() 
2119            Id = GetPatternTreeItemId(G2frame,G2frame.root, 'Notebook')
2120            if Id: G2frame.PatternTree.SetItemPyData(Id,data)
2121        elif 'Phase Data for' in G2frame.dataFrame.GetLabel():
2122            if G2frame.dataDisplay: 
2123                oldPage = G2frame.dataDisplay.GetSelection()
2124        G2frame.dataFrame.Clear()
2125        G2frame.dataFrame.SetLabel('')
2126    else:
2127        #create the frame for the data item window
2128        G2frame.dataFrame = DataFrame(parent=G2frame.mainPanel)
2129
2130    G2frame.dataFrame.Raise()           
2131    G2frame.PickId = 0
2132    parentID = G2frame.root
2133    G2frame.ExportPattern.Enable(False)
2134    defWid = [250,150]
2135    if item != G2frame.root:
2136        parentID = G2frame.PatternTree.GetItemParent(item)
2137    if G2frame.PatternTree.GetItemParent(item) == G2frame.root:
2138        G2frame.PatternId = item
2139        G2frame.PickId = item
2140        if G2frame.PatternTree.GetItemText(item) == 'Notebook':
2141            G2frame.dataFrame.SetMenuBar(G2frame.dataFrame.DataNotebookMenu)
2142            G2frame.PatternId = 0
2143            G2frame.ExportPattern.Enable(False)
2144            data = G2frame.PatternTree.GetItemPyData(item)
2145            UpdateNotebook(G2frame,data)
2146        elif G2frame.PatternTree.GetItemText(item) == 'Controls':
2147            G2frame.PatternId = 0
2148            G2frame.ExportPattern.Enable(False)
2149            data = G2frame.PatternTree.GetItemPyData(item)
2150            if not data:           #fill in defaults
2151                data = {
2152                    #least squares controls
2153                    'deriv type':'analytic Hessian','min dM/M':0.0001,'shift factor':1.0,'max cyc':3}
2154                G2frame.PatternTree.SetItemPyData(item,data)                             
2155            G2frame.Refine.Enable(True)
2156            G2frame.SeqRefine.Enable(True)
2157            UpdateControls(G2frame,data)
2158        elif G2frame.PatternTree.GetItemText(item) == 'Sequental results':
2159            data = G2frame.PatternTree.GetItemPyData(item)
2160            UpdateSeqResults(G2frame,data)           
2161        elif G2frame.PatternTree.GetItemText(item) == 'Covariance':
2162            data = G2frame.PatternTree.GetItemPyData(item)
2163            G2frame.dataFrame.setSizePosLeft(defWid)
2164            text = ''
2165            if 'Rvals' in data:
2166                Nvars = len(data['varyList'])
2167                Rvals = data['Rvals']
2168                text = '\nFinal residuals: \nRwp = %.3f%% \nchi**2 = %.1f \nGOF = %.2f'%(Rvals['Rwp'],Rvals['chisq'],Rvals['GOF'])
2169                text += '\nNobs = %d \nNvals = %d'%(Rvals['Nobs'],Nvars)
2170                if 'lamMax' in Rvals:
2171                    text += '\nlog10 MaxLambda = %.1f'%(np.log10(Rvals['lamMax']))
2172            wx.TextCtrl(parent=G2frame.dataFrame,size=G2frame.dataFrame.GetClientSize(),
2173                value='See plot window for covariance display'+text,style=wx.TE_MULTILINE)
2174            G2plt.PlotCovariance(G2frame)
2175        elif G2frame.PatternTree.GetItemText(item) == 'Constraints':
2176            data = G2frame.PatternTree.GetItemPyData(item)
2177            UpdateConstraints(G2frame,data)
2178        elif G2frame.PatternTree.GetItemText(item) == 'Restraints':
2179            data = G2frame.PatternTree.GetItemPyData(item)
2180            Phases = G2frame.GetPhaseData()
2181            phase = ''
2182            if Phases:
2183                phaseName = Phases.keys()[0]
2184            UpdateRestraints(G2frame,data,Phases,phaseName)
2185        elif 'IMG' in G2frame.PatternTree.GetItemText(item):
2186            G2frame.Image = item
2187            G2plt.PlotImage(G2frame,newPlot=True)
2188        elif 'PKS' in G2frame.PatternTree.GetItemText(item):
2189            G2plt.PlotPowderLines(G2frame)
2190        elif 'PWDR' in G2frame.PatternTree.GetItemText(item):
2191            G2frame.ExportPattern.Enable(True)
2192            UpdatePWHKPlot(G2frame,'PWDR',item)
2193        elif 'HKLF' in G2frame.PatternTree.GetItemText(item):
2194            G2frame.Sngl = item
2195            UpdatePWHKPlot(G2frame,'HKLF',item)
2196        elif 'PDF' in G2frame.PatternTree.GetItemText(item):
2197            G2frame.PatternId = item
2198            G2frame.ExportPDF.Enable(True)
2199            G2plt.PlotISFG(G2frame,type='S(Q)')
2200        elif G2frame.PatternTree.GetItemText(item) == 'Phases':
2201            G2frame.dataFrame.setSizePosLeft(defWid)
2202            wx.TextCtrl(parent=G2frame.dataFrame,size=G2frame.dataFrame.GetClientSize(),
2203                value='Select one phase to see its parameters')           
2204    elif 'I(Q)' in G2frame.PatternTree.GetItemText(item):
2205        G2frame.PickId = item
2206        G2frame.PatternId = G2frame.PatternTree.GetItemParent(item)
2207        G2plt.PlotISFG(G2frame,type='I(Q)',newPlot=True)
2208    elif 'S(Q)' in G2frame.PatternTree.GetItemText(item):
2209        G2frame.PickId = item
2210        G2frame.PatternId = G2frame.PatternTree.GetItemParent(item)
2211        G2plt.PlotISFG(G2frame,type='S(Q)',newPlot=True)
2212    elif 'F(Q)' in G2frame.PatternTree.GetItemText(item):
2213        G2frame.PickId = item
2214        G2frame.PatternId = G2frame.PatternTree.GetItemParent(item)
2215        G2plt.PlotISFG(G2frame,type='F(Q)',newPlot=True)
2216    elif 'G(R)' in G2frame.PatternTree.GetItemText(item):
2217        G2frame.PickId = item
2218        G2frame.PatternId = G2frame.PatternTree.GetItemParent(item)
2219        G2plt.PlotISFG(G2frame,type='G(R)',newPlot=True)           
2220    elif G2frame.PatternTree.GetItemText(parentID) == 'Phases':
2221        G2frame.PickId = item
2222        data = G2frame.PatternTree.GetItemPyData(item)
2223        G2phG.UpdatePhaseData(G2frame,item,data,oldPage)
2224    elif G2frame.PatternTree.GetItemText(item) == 'Comments':
2225        G2frame.dataFrame.SetMenuBar(G2frame.dataFrame.DataCommentsMenu)
2226        G2frame.PatternId = G2frame.PatternTree.GetItemParent(item)
2227        G2frame.PickId = item
2228        data = G2frame.PatternTree.GetItemPyData(item)
2229        UpdateComments(G2frame,data)
2230    elif G2frame.PatternTree.GetItemText(item) == 'Image Controls':
2231        G2frame.dataFrame.SetTitle('Image Controls')
2232        G2frame.PickId = item
2233        G2frame.Image = G2frame.PatternTree.GetItemParent(item)
2234        masks = G2frame.PatternTree.GetItemPyData(
2235            GetPatternTreeItemId(G2frame,G2frame.Image, 'Masks'))
2236        data = G2frame.PatternTree.GetItemPyData(item)
2237        G2imG.UpdateImageControls(G2frame,data,masks)
2238        G2plt.PlotImage(G2frame)
2239    elif G2frame.PatternTree.GetItemText(item) == 'Masks':
2240        G2frame.dataFrame.SetTitle('Masks')
2241        G2frame.PickId = item
2242        G2frame.Image = G2frame.PatternTree.GetItemParent(item)
2243        data = G2frame.PatternTree.GetItemPyData(item)
2244        G2imG.UpdateMasks(G2frame,data)
2245        G2plt.PlotImage(G2frame)
2246    elif G2frame.PatternTree.GetItemText(item) == 'Stress/Strain':
2247        G2frame.dataFrame.SetTitle('Stress/Strain')
2248        G2frame.PickId = item
2249        G2frame.Image = G2frame.PatternTree.GetItemParent(item)
2250        data = G2frame.PatternTree.GetItemPyData(item)
2251        G2imG.UpdateStressStrain(G2frame,data)
2252        G2plt.PlotImage(G2frame)
2253    elif G2frame.PatternTree.GetItemText(item) == 'HKL Plot Controls':
2254        G2frame.PickId = item
2255        G2frame.Sngl = G2frame.PatternTree.GetItemParent(item)
2256        data = G2frame.PatternTree.GetItemPyData(item)
2257        UpdateHKLControls(G2frame,data)
2258        G2plt.PlotSngl(G2frame)
2259    elif G2frame.PatternTree.GetItemText(item) == 'PDF Controls':
2260        G2frame.PatternId = G2frame.PatternTree.GetItemParent(item)
2261        G2frame.ExportPDF.Enable(True)
2262        G2frame.PickId = item
2263        data = G2frame.PatternTree.GetItemPyData(item)
2264        G2pdG.UpdatePDFGrid(G2frame,data)
2265        G2plt.PlotISFG(G2frame,type='I(Q)')
2266        G2plt.PlotISFG(G2frame,type='S(Q)')
2267        G2plt.PlotISFG(G2frame,type='F(Q)')
2268        G2plt.PlotISFG(G2frame,type='G(R)')
2269    elif G2frame.PatternTree.GetItemText(item) == 'Peak List':
2270        G2frame.PatternId = G2frame.PatternTree.GetItemParent(item)
2271        G2frame.ExportPeakList.Enable(True)
2272        G2frame.PickId = item
2273        data = G2frame.PatternTree.GetItemPyData(item)
2274        G2pdG.UpdatePeakGrid(G2frame,data)
2275        G2plt.PlotPatterns(G2frame)
2276    elif G2frame.PatternTree.GetItemText(item) == 'Background':
2277        G2frame.PatternId = G2frame.PatternTree.GetItemParent(item)
2278        G2frame.PickId = item
2279        data = G2frame.PatternTree.GetItemPyData(item)
2280        G2pdG.UpdateBackground(G2frame,data)
2281        G2plt.PlotPatterns(G2frame)
2282    elif G2frame.PatternTree.GetItemText(item) == 'Limits':
2283        G2frame.PatternId = G2frame.PatternTree.GetItemParent(item)
2284        G2frame.PickId = item
2285        data = G2frame.PatternTree.GetItemPyData(item)
2286        G2pdG.UpdateLimitsGrid(G2frame,data)
2287        G2plt.PlotPatterns(G2frame)
2288    elif G2frame.PatternTree.GetItemText(item) == 'Instrument Parameters':
2289        G2frame.PatternId = G2frame.PatternTree.GetItemParent(item)
2290        G2frame.PickId = item
2291        data = G2frame.PatternTree.GetItemPyData(item)
2292        G2pdG.UpdateInstrumentGrid(G2frame,data)
2293        G2plt.PlotPeakWidths(G2frame)
2294    elif G2frame.PatternTree.GetItemText(item) == 'Sample Parameters':
2295        G2frame.PatternId = G2frame.PatternTree.GetItemParent(item)
2296        G2frame.PickId = item
2297        data = G2frame.PatternTree.GetItemPyData(item)
2298
2299        if 'Temperature' not in data:           #temp fix for old gpx files
2300            data = {'Scale':[1.0,True],'Type':'Debye-Scherrer','Absorption':[0.0,False],'DisplaceX':[0.0,False],
2301                'DisplaceY':[0.0,False],'Diffuse':[],'Temperature':300.,'Pressure':1.0,'Humidity':0.0,'Voltage':0.0,
2302                'Force':0.0,'Gonio. radius':200.0}
2303            G2frame.PatternTree.SetItemPyData(item,data)
2304   
2305        G2pdG.UpdateSampleGrid(G2frame,data)
2306        G2plt.PlotPatterns(G2frame)
2307    elif G2frame.PatternTree.GetItemText(item) == 'Index Peak List':
2308        G2frame.PatternId = G2frame.PatternTree.GetItemParent(item)
2309        G2frame.ExportPeakList.Enable(True)
2310        G2frame.PickId = item
2311        data = G2frame.PatternTree.GetItemPyData(item)
2312        G2pdG.UpdateIndexPeaksGrid(G2frame,data)
2313        if 'PKS' in G2frame.PatternTree.GetItemText(G2frame.PatternId):
2314            G2plt.PlotPowderLines(G2frame)
2315        else:
2316            G2plt.PlotPatterns(G2frame)
2317    elif G2frame.PatternTree.GetItemText(item) == 'Unit Cells List':
2318        G2frame.PatternId = G2frame.PatternTree.GetItemParent(item)
2319        G2frame.PickId = item
2320        data = G2frame.PatternTree.GetItemPyData(item)
2321        if not data:
2322            data.append([0,0.0,4,25.0,0,'P1',1,1,1,90,90,90]) #zero error flag, zero value, max Nc/No, start volume
2323            data.append([0,0,0,0,0,0,0,0,0,0,0,0,0,0])      #Bravais lattice flags
2324            data.append([])                                 #empty cell list
2325            data.append([])                                 #empty dmin
2326            G2frame.PatternTree.SetItemPyData(item,data)                             
2327        G2pdG.UpdateUnitCellsGrid(G2frame,data)
2328        if 'PKS' in G2frame.PatternTree.GetItemText(G2frame.PatternId):
2329            G2plt.PlotPowderLines(G2frame)
2330        else:
2331            G2plt.PlotPatterns(G2frame)
2332    elif G2frame.PatternTree.GetItemText(item) == 'Reflection Lists':   #powder reflections
2333        G2frame.PatternId = G2frame.PatternTree.GetItemParent(item)
2334        G2frame.PickId = item
2335        data = G2frame.PatternTree.GetItemPyData(item)
2336        G2frame.RefList = ''
2337        if len(data):
2338            G2frame.RefList = data.keys()[0]
2339        G2pdG.UpdateReflectionGrid(G2frame,data)
2340        G2plt.PlotPatterns(G2frame)
2341    elif G2frame.PatternTree.GetItemText(item) == 'Reflection List':    #HKLF reflections
2342        G2frame.PatternId = G2frame.PatternTree.GetItemParent(item)
2343        name = G2frame.PatternTree.GetItemText(G2frame.PatternId)
2344        data = G2frame.PatternTree.GetItemPyData(G2frame.PatternId)
2345        G2pdG.UpdateReflectionGrid(G2frame,data,HKLF=True,Name=name)
Note: See TracBrowser for help on using the repository browser.