source: trunk/GSASIIgrid.py @ 698

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

implement Pawley update from reflection list
a bit more for stress/atrain

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