source: trunk/GSASIIgrid.py @ 752

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

add peak distance, view point selection & distance options
allow modification of view direction

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