source: trunk/GSASIIgrid.py @ 687

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

histogram wtFactors for PWDR & HKLF (latter not implemented yet)
means that data[0] is now {'wtFactor':1.0} instead of a mostly unused file name
also put in atomIndx for doing restraint calcs.

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