source: trunk/GSASIIgrid.py @ 696

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

begin implementation of image strain analysis - GUI stuff first
make image plot respond & clean up display some.
fix atom selection so N can be selected from periodic table
remove crash when Pawley refl not found in reflection set - it's now skipped

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