source: trunk/GSASIIgrid.py @ 740

Last change on this file since 740 was 740, checked in by vondreele, 10 years ago

bug fixes

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