source: trunk/GSASIIgrid.py @ 1831

Last change on this file since 1831 was 1831, checked in by toby, 7 years ago

move remaining generic controls to G2ctrls

  • Property svn:eol-style set to native
  • Property svn:keywords set to Date Author Revision URL Id
File size: 152.4 KB
Line 
1# -*- coding: utf-8 -*-
2#GSASIIgrid - data display routines
3########### SVN repository information ###################
4# $Date: 2015-05-01 23:38:23 +0000 (Fri, 01 May 2015) $
5# $Author: toby $
6# $Revision: 1831 $
7# $URL: trunk/GSASIIgrid.py $
8# $Id: GSASIIgrid.py 1831 2015-05-01 23:38:23Z toby $
9########### SVN repository information ###################
10'''
11*GSASIIgrid: Basic GUI routines*
12--------------------------------
13
14'''
15import wx
16import wx.grid as wg
17#import wx.wizard as wz
18#import wx.aui
19import wx.lib.scrolledpanel as wxscroll
20import time
21import copy
22import cPickle
23import sys
24import os
25import numpy as np
26import numpy.ma as ma
27import scipy.optimize as so
28import GSASIIpath
29GSASIIpath.SetVersionNumber("$Revision: 1831 $")
30import GSASIImath as G2mth
31import GSASIIIO as G2IO
32import GSASIIstrIO as G2stIO
33import GSASIIlattice as G2lat
34import GSASIIplot as G2plt
35import GSASIIpwdGUI as G2pdG
36import GSASIIimgGUI as G2imG
37import GSASIIphsGUI as G2phG
38import GSASIIspc as G2spc
39import GSASIImapvars as G2mv
40import GSASIIconstrGUI as G2cnstG
41import GSASIIrestrGUI as G2restG
42import GSASIIpy3 as G2py3
43import GSASIIobj as G2obj
44import GSASIIexprGUI as G2exG
45import GSASIIlog as log
46import GSASIIctrls as G2G
47
48# trig functions in degrees
49sind = lambda x: np.sin(x*np.pi/180.)
50tand = lambda x: np.tan(x*np.pi/180.)
51cosd = lambda x: np.cos(x*np.pi/180.)
52
53# Define a short name for convenience
54WACV = wx.ALIGN_CENTER_VERTICAL
55
56[ wxID_FOURCALC, wxID_FOURSEARCH, wxID_FOURCLEAR, wxID_PEAKSMOVE, wxID_PEAKSCLEAR, 
57    wxID_CHARGEFLIP, wxID_PEAKSUNIQUE, wxID_PEAKSDELETE, wxID_PEAKSDA,
58    wxID_PEAKSDISTVP, wxID_PEAKSVIEWPT, wxID_FINDEQVPEAKS,wxID_SHOWBONDS,wxID_MULTIMCSA,
59    wxID_SINGLEMCSA, wxID_4DMAPCOMPUTE,wxID_4DCHARGEFLIP,
60] = [wx.NewId() for item in range(17)]
61
62[ wxID_PWDRADD, wxID_HKLFADD, wxID_PWDANALYSIS, wxID_PWDCOPY, wxID_PLOTCTRLCOPY, 
63    wxID_DATADELETE,wxID_DATACOPY,wxID_DATACOPYFLAGS,wxID_DATASELCOPY,
64] = [wx.NewId() for item in range(9)]
65
66[ wxID_ATOMSEDITADD, wxID_ATOMSEDITINSERT, wxID_ATOMSEDITDELETE, wxID_ATOMSREFINE, 
67    wxID_ATOMSMODIFY, wxID_ATOMSTRANSFORM, wxID_ATOMSVIEWADD, wxID_ATOMVIEWINSERT,
68    wxID_RELOADDRAWATOMS,wxID_ATOMSDISAGL,wxID_ATOMMOVE,wxID_MAKEMOLECULE,
69    wxID_ASSIGNATMS2RB,wxID_ATOMSPDISAGL, wxID_ISODISP,
70] = [wx.NewId() for item in range(15)]
71
72[ wxID_DRAWATOMSTYLE, wxID_DRAWATOMLABEL, wxID_DRAWATOMCOLOR, wxID_DRAWATOMRESETCOLOR, 
73    wxID_DRAWVIEWPOINT, wxID_DRAWTRANSFORM, wxID_DRAWDELETE, wxID_DRAWFILLCELL, 
74    wxID_DRAWADDEQUIV, wxID_DRAWFILLCOORD, wxID_DRAWDISAGLTOR,  wxID_DRAWPLANE,
75    wxID_DRAWDISTVP,
76] = [wx.NewId() for item in range(13)]
77
78[ wxID_DRAWRESTRBOND, wxID_DRAWRESTRANGLE, wxID_DRAWRESTRPLANE, wxID_DRAWRESTRCHIRAL,
79] = [wx.NewId() for item in range(4)]
80
81[ wxID_ADDMCSAATOM,wxID_ADDMCSARB,wxID_CLEARMCSARB,wxID_MOVEMCSA,wxID_MCSACLEARRESULTS,
82] = [wx.NewId() for item in range(5)]
83
84[ wxID_CLEARTEXTURE,wxID_REFINETEXTURE,
85] = [wx.NewId() for item in range(2)]
86
87[ wxID_PAWLEYLOAD, wxID_PAWLEYESTIMATE, wxID_PAWLEYUPDATE,
88] = [wx.NewId() for item in range(3)]
89
90[ wxID_IMCALIBRATE,wxID_IMRECALIBRATE,wxID_IMINTEGRATE, wxID_IMCLEARCALIB, 
91    wxID_IMCOPYCONTROLS, wxID_INTEGRATEALL, wxID_IMSAVECONTROLS, wxID_IMLOADCONTROLS,
92] = [wx.NewId() for item in range(8)]
93
94[ wxID_MASKCOPY, wxID_MASKSAVE, wxID_MASKLOAD, wxID_NEWMASKSPOT,wxID_NEWMASKARC,wxID_NEWMASKRING,
95    wxID_NEWMASKFRAME, wxID_NEWMASKPOLY,  wxID_MASKLOADNOT,
96] = [wx.NewId() for item in range(9)]
97
98[ wxID_STRSTACOPY, wxID_STRSTAFIT, wxID_STRSTASAVE, wxID_STRSTALOAD,wxID_STRSTSAMPLE,
99    wxID_APPENDDZERO,wxID_STRSTAALLFIT,wxID_UPDATEDZERO,
100] = [wx.NewId() for item in range(8)]
101
102[ wxID_BACKCOPY,wxID_LIMITCOPY, wxID_SAMPLECOPY, wxID_SAMPLECOPYSOME, wxID_BACKFLAGCOPY, wxID_SAMPLEFLAGCOPY,
103    wxID_SAMPLESAVE, wxID_SAMPLELOAD,wxID_ADDEXCLREGION,wxID_SETSCALE,wxID_SAMPLE1VAL,wxID_ALLSAMPLELOAD,
104    wxID_PEAKSMOVE,
105] = [wx.NewId() for item in range(13)]
106
107[ wxID_INSTPRMRESET,wxID_CHANGEWAVETYPE,wxID_INSTCOPY, wxID_INSTFLAGCOPY, wxID_INSTLOAD,
108    wxID_INSTSAVE, wxID_INST1VAL, wxID_INSTCALIB,
109] = [wx.NewId() for item in range(8)]
110
111[ wxID_UNDO,wxID_LSQPEAKFIT,wxID_LSQONECYCLE,wxID_RESETSIGGAM,wxID_CLEARPEAKS,wxID_AUTOSEARCH,
112    wxID_PEAKSCOPY, wxID_SEQPEAKFIT,
113] = [wx.NewId() for item in range(8)]
114
115[  wxID_INDXRELOAD, wxID_INDEXPEAKS, wxID_REFINECELL, wxID_COPYCELL, wxID_MAKENEWPHASE,
116] = [wx.NewId() for item in range(5)]
117
118[ wxID_CONSTRAINTADD,wxID_EQUIVADD,wxID_HOLDADD,wxID_FUNCTADD,
119  wxID_CONSPHASE, wxID_CONSHIST, wxID_CONSHAP, wxID_CONSGLOBAL,
120] = [wx.NewId() for item in range(8)]
121
122[ wxID_RESTRAINTADD, wxID_RESTSELPHASE,wxID_RESTDELETE, wxID_RESRCHANGEVAL, 
123    wxID_RESTCHANGEESD,wxID_AARESTRAINTADD,wxID_AARESTRAINTPLOT,
124] = [wx.NewId() for item in range(7)]
125
126[ wxID_RIGIDBODYADD,wxID_DRAWDEFINERB,wxID_RIGIDBODYIMPORT,wxID_RESIDUETORSSEQ,
127    wxID_AUTOFINDRESRB,wxID_GLOBALRESREFINE,wxID_RBREMOVEALL,wxID_COPYRBPARMS,
128    wxID_GLOBALTHERM,wxID_VECTORBODYADD
129] = [wx.NewId() for item in range(10)]
130
131[ wxID_RENAMESEQSEL,wxID_SAVESEQSEL,wxID_SAVESEQSELCSV,wxID_SAVESEQCSV,wxID_PLOTSEQSEL,
132  wxID_ORGSEQSEL,wxADDSEQVAR,wxDELSEQVAR,wxEDITSEQVAR,wxCOPYPARFIT,wxID_AVESEQSEL,
133  wxADDPARFIT,wxDELPARFIT,wxEDITPARFIT,wxDOPARFIT,
134] = [wx.NewId() for item in range(15)]
135
136[ wxID_MODELCOPY,wxID_MODELFIT,wxID_MODELADD,wxID_ELEMENTADD,wxID_ELEMENTDELETE,
137    wxID_ADDSUBSTANCE,wxID_LOADSUBSTANCE,wxID_DELETESUBSTANCE,wxID_COPYSUBSTANCE,
138    wxID_MODELUNDO,wxID_MODELFITALL,wxID_MODELCOPYFLAGS,
139] = [wx.NewId() for item in range(12)]
140
141[ wxID_SELECTPHASE,wxID_PWDHKLPLOT,wxID_PWD3DHKLPLOT,wxID_3DALLHKLPLOT,
142] = [wx.NewId() for item in range(4)]
143
144[ wxID_PDFCOPYCONTROLS, wxID_PDFSAVECONTROLS, wxID_PDFLOADCONTROLS, 
145    wxID_PDFCOMPUTE, wxID_PDFCOMPUTEALL, wxID_PDFADDELEMENT, wxID_PDFDELELEMENT,
146] = [wx.NewId() for item in range(7)]
147
148[ wxID_MCRON,wxID_MCRLIST,wxID_MCRSAVE,wxID_MCRPLAY,
149] = [wx.NewId() for item in range(4)]
150
151VERY_LIGHT_GREY = wx.Colour(235,235,235)
152
153# Aliases for Classes/Functions moved to GSASIIctrls, all should be tracked down but leaving as a reminder
154#SingleFloatDialog = G2G.SingleFloatDialog
155#SingleStringDialog = G2G.SingleStringDialog
156#MultiStringDialog = G2G.MultiStringDialog
157#G2ColumnIDDialog = G2G.G2ColumnIDDialog
158#ItemSelector = G2G.ItemSelector
159#HorizontalLine = G2G.HorizontalLine
160#G2LoggedButton = G2G.G2LoggedButton
161#EnumSelector = G2G.EnumSelector
162#G2ChoiceButton = G2G.G2ChoiceButton
163#GSGrid = G2G.GSGrid
164#Table = G2G.Table
165#GridFractionEditor = G2G.GridFractionEditor
166#GSNoteBook = G2G.GSNoteBook
167
168# Should SGMessageBox, SymOpDialog, DisAglDialog be moved?
169
170################################################################################
171#### GSAS-II class definitions
172################################################################################
173
174class SGMessageBox(wx.Dialog):
175    ''' Special version of MessageBox that displays space group & super space group text
176    in two blocks
177    '''
178    def __init__(self,parent,title,text,table,):
179        wx.Dialog.__init__(self,parent,wx.ID_ANY,title,pos=wx.DefaultPosition,
180            style=wx.DEFAULT_DIALOG_STYLE|wx.RESIZE_BORDER)
181        self.text=text
182        self.table = table
183        self.panel = wx.Panel(self)
184        mainSizer = wx.BoxSizer(wx.VERTICAL)
185        mainSizer.Add((0,10))
186        for line in text:
187            mainSizer.Add(wx.StaticText(self.panel,label='     %s     '%(line)),0,WACV)
188        ncol = self.table[0].count(',')+1
189        tableSizer = wx.FlexGridSizer(0,2*ncol+3,0,0)
190        for j,item in enumerate(self.table):
191            num,flds = item.split(')')
192            tableSizer.Add(wx.StaticText(self.panel,label='     %s  '%(num+')')),0,WACV|wx.ALIGN_LEFT)           
193            flds = flds.replace(' ','').split(',')
194            for i,fld in enumerate(flds):
195                if i < ncol-1:
196                    tableSizer.Add(wx.StaticText(self.panel,label='%s, '%(fld)),0,WACV|wx.ALIGN_RIGHT)
197                else:
198                    tableSizer.Add(wx.StaticText(self.panel,label='%s'%(fld)),0,WACV|wx.ALIGN_RIGHT)
199            if not j%2:
200                tableSizer.Add((20,0))
201        mainSizer.Add(tableSizer,0,wx.ALIGN_LEFT)
202        btnsizer = wx.StdDialogButtonSizer()
203        OKbtn = wx.Button(self.panel, wx.ID_OK)
204        OKbtn.SetDefault()
205        btnsizer.AddButton(OKbtn)
206        btnsizer.Realize()
207        mainSizer.Add((0,10))
208        mainSizer.Add(btnsizer,0,wx.ALIGN_CENTER)
209        self.panel.SetSizer(mainSizer)
210        self.panel.Fit()
211        self.Fit()
212        size = self.GetSize()
213        self.SetSize([size[0]+20,size[1]])
214
215    def Show(self):
216        '''Use this method after creating the dialog to post it
217        '''
218        self.ShowModal()
219        return
220
221################################################################################
222class SymOpDialog(wx.Dialog):
223    '''Class to select a symmetry operator
224    '''
225    def __init__(self,parent,SGData,New=True,ForceUnit=False):
226        wx.Dialog.__init__(self,parent,-1,'Select symmetry operator',
227            pos=wx.DefaultPosition,style=wx.DEFAULT_DIALOG_STYLE)
228        panel = wx.Panel(self)
229        self.SGData = SGData
230        self.New = New
231        self.Force = ForceUnit
232        self.OpSelected = [0,0,0,[0,0,0],False,False]
233        mainSizer = wx.BoxSizer(wx.VERTICAL)
234        if ForceUnit:
235            choice = ['No','Yes']
236            self.force = wx.RadioBox(panel,-1,'Force to unit cell?',choices=choice)
237            self.force.Bind(wx.EVT_RADIOBOX, self.OnOpSelect)
238            mainSizer.Add(self.force,0,WACV)
239        mainSizer.Add((5,5),0)
240        if SGData['SGInv']:
241            choice = ['No','Yes']
242            self.inv = wx.RadioBox(panel,-1,'Choose inversion?',choices=choice)
243            self.inv.Bind(wx.EVT_RADIOBOX, self.OnOpSelect)
244            mainSizer.Add(self.inv,0,WACV)
245        mainSizer.Add((5,5),0)
246        if SGData['SGLatt'] != 'P':
247            LattOp = G2spc.Latt2text(SGData['SGLatt']).split(';')
248            self.latt = wx.RadioBox(panel,-1,'Choose cell centering?',choices=LattOp)
249            self.latt.Bind(wx.EVT_RADIOBOX, self.OnOpSelect)
250            mainSizer.Add(self.latt,0,WACV)
251        mainSizer.Add((5,5),0)
252        if SGData['SGLaue'] in ['-1','2/m','mmm','4/m','4/mmm']:
253            Ncol = 2
254        else:
255            Ncol = 3
256        OpList = []
257        for Opr in SGData['SGOps']:
258            OpList.append(G2spc.MT2text(Opr))
259        self.oprs = wx.RadioBox(panel,-1,'Choose space group operator?',choices=OpList,
260            majorDimension=Ncol)
261        self.oprs.Bind(wx.EVT_RADIOBOX, self.OnOpSelect)
262        mainSizer.Add(self.oprs,0,WACV)
263        mainSizer.Add((5,5),0)
264        mainSizer.Add(wx.StaticText(panel,-1,"   Choose unit cell?"),0,WACV)
265        mainSizer.Add((5,5),0)
266        cellSizer = wx.BoxSizer(wx.HORIZONTAL)
267        cellSizer.Add((5,0),0)
268        cellName = ['X','Y','Z']
269        self.cell = []
270        for i in range(3):
271            self.cell.append(wx.SpinCtrl(panel,-1,cellName[i],size=wx.Size(50,20)))
272            self.cell[-1].SetRange(-3,3)
273            self.cell[-1].SetValue(0)
274            self.cell[-1].Bind(wx.EVT_SPINCTRL, self.OnOpSelect)
275            cellSizer.Add(self.cell[-1],0,WACV)
276        mainSizer.Add(cellSizer,0,)
277        if self.New:
278            choice = ['No','Yes']
279            self.new = wx.RadioBox(panel,-1,'Generate new positions?',choices=choice)
280            self.new.Bind(wx.EVT_RADIOBOX, self.OnOpSelect)
281            mainSizer.Add(self.new,0,WACV)
282        mainSizer.Add((5,5),0)
283
284        OkBtn = wx.Button(panel,-1,"Ok")
285        OkBtn.Bind(wx.EVT_BUTTON, self.OnOk)
286        cancelBtn = wx.Button(panel,-1,"Cancel")
287        cancelBtn.Bind(wx.EVT_BUTTON, self.OnCancel)
288        btnSizer = wx.BoxSizer(wx.HORIZONTAL)
289        btnSizer.Add((20,20),1)
290        btnSizer.Add(OkBtn)
291        btnSizer.Add((20,20),1)
292        btnSizer.Add(cancelBtn)
293        btnSizer.Add((20,20),1)
294
295        mainSizer.Add(btnSizer,0,wx.EXPAND|wx.BOTTOM|wx.TOP, 10)
296        panel.SetSizer(mainSizer)
297        panel.Fit()
298        self.Fit()
299
300    def OnOpSelect(self,event):
301        if self.SGData['SGInv']:
302            self.OpSelected[0] = self.inv.GetSelection()
303        if self.SGData['SGLatt'] != 'P':
304            self.OpSelected[1] = self.latt.GetSelection()
305        self.OpSelected[2] = self.oprs.GetSelection()
306        for i in range(3):
307            self.OpSelected[3][i] = float(self.cell[i].GetValue())
308        if self.New:
309            self.OpSelected[4] = self.new.GetSelection()
310        if self.Force:
311            self.OpSelected[5] = self.force.GetSelection()
312
313    def GetSelection(self):
314        return self.OpSelected
315
316    def OnOk(self,event):
317        parent = self.GetParent()
318        parent.Raise()
319        self.EndModal(wx.ID_OK)
320
321    def OnCancel(self,event):
322        parent = self.GetParent()
323        parent.Raise()
324        self.EndModal(wx.ID_CANCEL)
325
326class DisAglDialog(wx.Dialog):
327    '''Distance/Angle Controls input dialog. After
328    :meth:`ShowModal` returns, the results are found in
329    dict :attr:`self.data`, which is accessed using :meth:`GetData`.
330
331    :param wx.Frame parent: reference to parent frame (or None)
332    :param dict data: a dict containing the current
333      search ranges or an empty dict, which causes default values
334      to be used.
335      Will be used to set element `DisAglCtls` in
336      :ref:`Phase Tree Item <Phase_table>`
337    :param dict default:  A dict containing the default
338      search ranges for each element.
339    '''
340    def __init__(self,parent,data,default):
341        wx.Dialog.__init__(self,parent,wx.ID_ANY,
342                           'Distance Angle Controls', 
343            pos=wx.DefaultPosition,style=wx.DEFAULT_DIALOG_STYLE)
344        self.default = default
345        self.panel = wx.Panel(self)         #just a dummy - gets destroyed in Draw!
346        self._default(data,self.default)
347        self.Draw(self.data)
348               
349    def _default(self,data,default):
350        '''Set starting values for the search values, either from
351        the input array or from defaults, if input is null
352        '''
353        if data:
354            self.data = copy.deepcopy(data) # don't mess with originals
355        else:
356            self.data = {}
357            self.data['Name'] = default['Name']
358            self.data['Factors'] = [0.85,0.85]
359            self.data['AtomTypes'] = default['AtomTypes']
360            self.data['BondRadii'] = default['BondRadii'][:]
361            self.data['AngleRadii'] = default['AngleRadii'][:]
362
363    def Draw(self,data):
364        '''Creates the contents of the dialog. Normally called
365        by :meth:`__init__`.
366        '''
367        self.panel.Destroy()
368        self.panel = wx.Panel(self)
369        mainSizer = wx.BoxSizer(wx.VERTICAL)
370        mainSizer.Add(wx.StaticText(self.panel,-1,'Controls for phase '+data['Name']),
371            0,WACV|wx.LEFT,10)
372        mainSizer.Add((10,10),1)
373       
374        radiiSizer = wx.FlexGridSizer(0,3,5,5)
375        radiiSizer.Add(wx.StaticText(self.panel,-1,' Type'),0,WACV)
376        radiiSizer.Add(wx.StaticText(self.panel,-1,'Bond radii'),0,WACV)
377        radiiSizer.Add(wx.StaticText(self.panel,-1,'Angle radii'),0,WACV)
378        self.objList = {}
379        for id,item in enumerate(self.data['AtomTypes']):
380            radiiSizer.Add(wx.StaticText(self.panel,-1,' '+item),0,WACV)
381            bRadii = wx.TextCtrl(self.panel,-1,value='%.3f'%(data['BondRadii'][id]),style=wx.TE_PROCESS_ENTER)
382            self.objList[bRadii.GetId()] = ['BondRadii',id]
383            bRadii.Bind(wx.EVT_TEXT_ENTER,self.OnRadiiVal)
384            bRadii.Bind(wx.EVT_KILL_FOCUS,self.OnRadiiVal)
385            radiiSizer.Add(bRadii,0,WACV)
386            aRadii = wx.TextCtrl(self.panel,-1,value='%.3f'%(data['AngleRadii'][id]),style=wx.TE_PROCESS_ENTER)
387            self.objList[aRadii.GetId()] = ['AngleRadii',id]
388            aRadii.Bind(wx.EVT_TEXT_ENTER,self.OnRadiiVal)
389            aRadii.Bind(wx.EVT_KILL_FOCUS,self.OnRadiiVal)
390            radiiSizer.Add(aRadii,0,WACV)
391        mainSizer.Add(radiiSizer,0,wx.EXPAND)
392        factorSizer = wx.FlexGridSizer(0,2,5,5)
393        Names = ['Bond','Angle']
394        for i,name in enumerate(Names):
395            factorSizer.Add(wx.StaticText(self.panel,-1,name+' search factor'),0,WACV)
396            bondFact = wx.TextCtrl(self.panel,-1,value='%.3f'%(data['Factors'][i]),style=wx.TE_PROCESS_ENTER)
397            self.objList[bondFact.GetId()] = ['Factors',i]
398            bondFact.Bind(wx.EVT_TEXT_ENTER,self.OnRadiiVal)
399            bondFact.Bind(wx.EVT_KILL_FOCUS,self.OnRadiiVal)
400            factorSizer.Add(bondFact)
401        mainSizer.Add(factorSizer,0,wx.EXPAND)
402       
403        OkBtn = wx.Button(self.panel,-1,"Ok")
404        OkBtn.Bind(wx.EVT_BUTTON, self.OnOk)
405        ResetBtn = wx.Button(self.panel,-1,'Reset')
406        ResetBtn.Bind(wx.EVT_BUTTON, self.OnReset)
407        btnSizer = wx.BoxSizer(wx.HORIZONTAL)
408        btnSizer.Add((20,20),1)
409        btnSizer.Add(OkBtn)
410        btnSizer.Add(ResetBtn)
411        btnSizer.Add((20,20),1)
412        mainSizer.Add(btnSizer,0,wx.EXPAND|wx.BOTTOM|wx.TOP, 10)
413        self.panel.SetSizer(mainSizer)
414        self.panel.Fit()
415        self.Fit()
416   
417    def OnRadiiVal(self,event):
418        Obj = event.GetEventObject()
419        item = self.objList[Obj.GetId()]
420        try:
421            self.data[item[0]][item[1]] = float(Obj.GetValue())
422        except ValueError:
423            pass
424        Obj.SetValue("%.3f"%(self.data[item[0]][item[1]]))          #reset in case of error
425       
426    def GetData(self):
427        'Returns the values from the dialog'
428        return self.data
429       
430    def OnOk(self,event):
431        'Called when the OK button is pressed'
432        parent = self.GetParent()
433        parent.Raise()
434        self.EndModal(wx.ID_OK)             
435       
436    def OnReset(self,event):
437        'Called when the Reset button is pressed'
438        data = {}
439        self._default(data,self.default)
440        self.Draw(self.data)
441               
442################################################################################
443class ShowLSParms(wx.Dialog):
444    '''Create frame to show least-squares parameters
445    '''
446    def __init__(self,parent,title,parmDict,varyList,fullVaryList,
447                 size=(300,430)):
448        wx.Dialog.__init__(self,parent,wx.ID_ANY,title,size=size,
449                           style=wx.DEFAULT_DIALOG_STYLE|wx.RESIZE_BORDER)
450        mainSizer = wx.BoxSizer(wx.VERTICAL)
451
452        panel = wxscroll.ScrolledPanel(
453            self, wx.ID_ANY,
454            #size=size,
455            style = wx.TAB_TRAVERSAL|wx.SUNKEN_BORDER)
456        num = len(varyList)
457        mainSizer.Add(wx.StaticText(self,wx.ID_ANY,'Number of refined variables: '+str(num)))
458        if len(varyList) != len(fullVaryList):
459            num = len(fullVaryList) - len(varyList)
460            mainSizer.Add(wx.StaticText(self,wx.ID_ANY,' + '+str(num)+' parameters are varied via constraints'))
461        subSizer = wx.FlexGridSizer(cols=4,hgap=2,vgap=2)
462        parmNames = parmDict.keys()
463        parmNames.sort()
464        subSizer.Add((-1,-1))
465        subSizer.Add(wx.StaticText(panel,wx.ID_ANY,'Parameter name  '))
466        subSizer.Add(wx.StaticText(panel,wx.ID_ANY,'refine?'))
467        subSizer.Add(wx.StaticText(panel,wx.ID_ANY,'value'),0,wx.ALIGN_RIGHT)
468        explainRefine = False
469        for name in parmNames:
470            # skip entries without numerical values
471            if isinstance(parmDict[name],basestring): continue
472            try:
473                value = G2py3.FormatSigFigs(parmDict[name])
474            except TypeError:
475                value = str(parmDict[name])+' -?' # unexpected
476                #continue
477            v = G2obj.getVarDescr(name)
478            if v is None or v[-1] is None:
479                subSizer.Add((-1,-1))
480            else:               
481                ch = G2G.HelpButton(panel,G2obj.fmtVarDescr(name))
482                subSizer.Add(ch,0,wx.LEFT|wx.RIGHT|WACV|wx.ALIGN_CENTER,1)
483            subSizer.Add(wx.StaticText(panel,wx.ID_ANY,str(name)))
484            if name in varyList:
485                subSizer.Add(wx.StaticText(panel,wx.ID_ANY,'R'))
486            elif name in fullVaryList:
487                subSizer.Add(wx.StaticText(panel,wx.ID_ANY,'C'))
488                explainRefine = True
489            else:
490                subSizer.Add((-1,-1))
491            subSizer.Add(wx.StaticText(panel,wx.ID_ANY,value),0,wx.ALIGN_RIGHT)
492
493        # finish up ScrolledPanel
494        panel.SetSizer(subSizer)
495        panel.SetAutoLayout(1)
496        panel.SetupScrolling()
497        mainSizer.Add(panel,1, wx.ALL|wx.EXPAND,1)
498
499        if explainRefine:
500            mainSizer.Add(
501                wx.StaticText(self,wx.ID_ANY,
502                          '"R" indicates a refined variable\n'+
503                          '"C" indicates generated from a constraint'
504                          ),
505                0, wx.ALL,0)
506        # make OK button
507        btnsizer = wx.BoxSizer(wx.HORIZONTAL)
508        btn = wx.Button(self, wx.ID_CLOSE,"Close") 
509        btn.Bind(wx.EVT_BUTTON,self._onClose)
510        btnsizer.Add(btn)
511        mainSizer.Add(btnsizer, 0, wx.ALIGN_CENTER|wx.ALL, 5)
512        # Allow window to be enlarged but not made smaller
513        self.SetSizer(mainSizer)
514        self.SetMinSize(self.GetSize())
515
516    def _onClose(self,event):
517        self.EndModal(wx.ID_CANCEL)
518 
519################################################################################
520class DataFrame(wx.Frame):
521    '''Create the data item window and all the entries in menus used in
522    that window. For Linux and windows, the menu entries are created for the
523    current data item window, but in the Mac the menu is accessed from all
524    windows. This means that a different menu is posted depending on which
525    data item is posted. On the Mac, all the menus contain the data tree menu
526    items, but additional menus are added specific to the data item.
527
528    Note that while the menus are created here,
529    the binding for the menus is done later in various GSASII*GUI modules,
530    where the functions to be called are defined.
531    '''
532    def Bind(self,eventtype,handler,*args,**kwargs):
533        '''Override the Bind() function: on the Mac the binding is to
534        the main window, so that menus operate with any window on top.
535        For other platforms, either wrap calls that will be logged
536        or call the default wx.Frame Bind() to bind to the menu item directly.
537
538        Note that bindings can be made to objects by Id or by direct reference to the
539        object. As a convention, when bindings are to objects, they are not logged
540        but when bindings are by Id, they are logged.
541        '''
542        if sys.platform == "darwin": # mac
543            self.G2frame.Bind(eventtype,handler,*args,**kwargs)
544            return
545        if eventtype == wx.EVT_MENU and 'id' in kwargs:
546            menulabels = log.SaveMenuCommand(kwargs['id'],self.G2frame,handler)
547            if menulabels:
548                #print 'intercepting bind for',handler,menulabels,kwargs['id']
549                wx.Frame.Bind(self,eventtype,self.G2frame.MenuBinding,*args,**kwargs)
550                return
551            wx.Frame.Bind(self,eventtype,handler,*args,**kwargs)     
552       
553    def PrefillDataMenu(self,menu,helpType,helpLbl=None,empty=False):
554        '''Create the "standard" part of data frame menus. Note that on Linux and
555        Windows nothing happens here. On Mac, this menu duplicates the
556        tree menu, but adds an extra help command for the data item and a separator.
557        '''
558        self.datamenu = menu
559        self.G2frame.dataMenuBars.append(menu)
560        self.helpType = helpType
561        self.helpLbl = helpLbl
562        if sys.platform == "darwin": # mac                         
563            self.G2frame.FillMainMenu(menu) # add the data tree menu items
564            if not empty:
565                menu.Append(wx.Menu(title=''),title='|') # add a separator
566       
567    def PostfillDataMenu(self,empty=False):
568        '''Create the "standard" part of data frame menus. Note that on Linux and
569        Windows, this is the standard help Menu. On Mac, this menu duplicates the
570        tree menu, but adds an extra help command for the data item and a separator.
571        '''
572        menu = self.datamenu
573        helpType = self.helpType
574        helpLbl = self.helpLbl
575        if sys.platform == "darwin": # mac
576            if not empty:
577                menu.Append(wx.Menu(title=''),title='|') # add another separator
578            menu.Append(G2G.AddHelp(self.G2frame,helpType=helpType, helpLbl=helpLbl),
579                        title='&Help')
580        else: # other
581            menu.Append(menu=G2G.MyHelp(self,helpType=helpType, helpLbl=helpLbl),
582                        title='&Help')
583
584    def _init_menus(self):
585        'define all GSAS-II data frame menus'
586
587        # for use where no menu or data frame help is provided
588        self.BlankMenu = wx.MenuBar()
589       
590        # Controls
591        self.ControlsMenu = wx.MenuBar()
592        self.PrefillDataMenu(self.ControlsMenu,helpType='Controls',empty=True)
593        self.PostfillDataMenu(empty=True)
594       
595        # Notebook
596        self.DataNotebookMenu = wx.MenuBar() 
597        self.PrefillDataMenu(self.DataNotebookMenu,helpType='Notebook',empty=True)
598        self.PostfillDataMenu(empty=True)
599       
600        # Comments
601        self.DataCommentsMenu = wx.MenuBar()
602        self.PrefillDataMenu(self.DataCommentsMenu,helpType='Comments',empty=True)
603        self.PostfillDataMenu(empty=True)
604       
605        # Constraints - something amiss here - get weird wx C++ error after refine!
606        self.ConstraintMenu = wx.MenuBar()
607        self.PrefillDataMenu(self.ConstraintMenu,helpType='Constraints')
608        self.ConstraintTab = wx.Menu(title='')
609        self.ConstraintMenu.Append(menu=self.ConstraintTab, title='Select tab')
610        for id,txt in (
611            (wxID_CONSPHASE,'Phase'),
612            (wxID_CONSHAP,'Histogram/Phase'),
613            (wxID_CONSHIST,'Histogram'),
614            (wxID_CONSGLOBAL,'Global')):
615            self.ConstraintTab.Append(
616                id=id, kind=wx.ITEM_NORMAL,text=txt,
617                help='Select '+txt+' constraint editing tab')
618        self.ConstraintEdit = wx.Menu(title='')
619        self.ConstraintMenu.Append(menu=self.ConstraintEdit, title='Edit')
620        self.ConstraintEdit.Append(id=wxID_HOLDADD, kind=wx.ITEM_NORMAL,text='Add hold',
621            help='Add hold on a parameter value')
622        self.ConstraintEdit.Append(id=wxID_EQUIVADD, kind=wx.ITEM_NORMAL,text='Add equivalence',
623            help='Add equivalence between parameter values')
624        self.ConstraintEdit.Append(id=wxID_CONSTRAINTADD, kind=wx.ITEM_NORMAL,text='Add constraint',
625            help='Add constraint on parameter values')
626        self.ConstraintEdit.Append(id=wxID_FUNCTADD, kind=wx.ITEM_NORMAL,text='Add New Var',
627            help='Add variable composed of existing parameter')
628        self.PostfillDataMenu()
629
630        # item = self.ConstraintEdit.Append(id=wx.ID_ANY,kind=wx.ITEM_NORMAL,text='Update GUI')
631        # def UpdateGSASIIconstrGUI(event):
632        #     import GSASIIconstrGUI
633        #     reload(GSASIIconstrGUI)
634        #     import GSASIIobj
635        #     reload(GSASIIobj)
636        # self.Bind(wx.EVT_MENU,UpdateGSASIIconstrGUI,id=item.GetId())
637
638        # Rigid bodies
639        self.RigidBodyMenu = wx.MenuBar()
640        self.PrefillDataMenu(self.RigidBodyMenu,helpType='Rigid bodies')
641        self.ResidueRBMenu = wx.Menu(title='')
642        self.ResidueRBMenu.Append(id=wxID_RIGIDBODYIMPORT, kind=wx.ITEM_NORMAL,text='Import XYZ',
643            help='Import rigid body XYZ from file')
644        self.ResidueRBMenu.Append(id=wxID_RESIDUETORSSEQ, kind=wx.ITEM_NORMAL,text='Define sequence',
645            help='Define torsion sequence')
646        self.ResidueRBMenu.Append(id=wxID_RIGIDBODYADD, kind=wx.ITEM_NORMAL,text='Import residues',
647            help='Import residue rigid bodies from macro file')
648        self.RigidBodyMenu.Append(menu=self.ResidueRBMenu, title='Edit Body')
649        self.PostfillDataMenu()
650
651        self.VectorBodyMenu = wx.MenuBar()
652        self.PrefillDataMenu(self.VectorBodyMenu,helpType='Vector rigid bodies')
653        self.VectorRBEdit = wx.Menu(title='')
654        self.VectorRBEdit.Append(id=wxID_VECTORBODYADD, kind=wx.ITEM_NORMAL,text='Add rigid body',
655            help='Add vector rigid body')
656        self.VectorBodyMenu.Append(menu=self.VectorRBEdit, title='Edit Vector Body')
657        self.PostfillDataMenu()
658
659                   
660        # Restraints
661        self.RestraintTab = wx.Menu(title='')
662        self.RestraintEdit = wx.Menu(title='')
663        self.RestraintEdit.Append(id=wxID_RESTSELPHASE, kind=wx.ITEM_NORMAL,text='Select phase',
664            help='Select phase')
665        self.RestraintEdit.Append(id=wxID_RESTRAINTADD, kind=wx.ITEM_NORMAL,text='Add restraints',
666            help='Add restraints')
667        self.RestraintEdit.Enable(wxID_RESTRAINTADD,True)    #gets disabled if macromolecule phase
668        self.RestraintEdit.Append(id=wxID_AARESTRAINTADD, kind=wx.ITEM_NORMAL,text='Add residue restraints',
669            help='Add residue based restraints for macromolecules from macro file')
670        self.RestraintEdit.Enable(wxID_AARESTRAINTADD,False)    #gets enabled if macromolecule phase
671        self.RestraintEdit.Append(id=wxID_AARESTRAINTPLOT, kind=wx.ITEM_NORMAL,text='Plot residue restraints',
672            help='Plot selected residue based restraints for macromolecules from macro file')
673        self.RestraintEdit.Enable(wxID_AARESTRAINTPLOT,False)    #gets enabled if macromolecule phase
674        self.RestraintEdit.Append(id=wxID_RESRCHANGEVAL, kind=wx.ITEM_NORMAL,text='Change value',
675            help='Change observed value')
676        self.RestraintEdit.Append(id=wxID_RESTCHANGEESD, kind=wx.ITEM_NORMAL,text='Change esd',
677            help='Change esd in observed value')
678        self.RestraintEdit.Append(id=wxID_RESTDELETE, kind=wx.ITEM_NORMAL,text='Delete restraints',
679            help='Delete selected restraints')
680
681        self.RestraintMenu = wx.MenuBar()
682        self.PrefillDataMenu(self.RestraintMenu,helpType='Restraints')
683        self.RestraintMenu.Append(menu=self.RestraintTab, title='Select tab')
684        self.RestraintMenu.Append(menu=self.RestraintEdit, title='Edit')
685        self.PostfillDataMenu()
686           
687        # Sequential results
688        self.SequentialMenu = wx.MenuBar()
689        self.PrefillDataMenu(self.SequentialMenu,helpType='Sequential',helpLbl='Sequential Refinement')
690        self.SequentialFile = wx.Menu(title='')
691        self.SequentialMenu.Append(menu=self.SequentialFile, title='Columns')
692        self.SequentialFile.Append(id=wxID_RENAMESEQSEL, kind=wx.ITEM_NORMAL,text='Rename selected',
693            help='Rename selected sequential refinement columns')
694        self.SequentialFile.Append(id=wxID_SAVESEQSEL, kind=wx.ITEM_NORMAL,text='Save selected as text',
695            help='Save selected sequential refinement results as a text file')
696        self.SequentialFile.Append(id=wxID_SAVESEQCSV, kind=wx.ITEM_NORMAL,text='Save all as CSV',
697            help='Save all sequential refinement results as a CSV spreadsheet file')
698        self.SequentialFile.Append(id=wxID_SAVESEQSELCSV, kind=wx.ITEM_NORMAL,text='Save selected as CSV',
699            help='Save selected sequential refinement results as a CSV spreadsheet file')
700        self.SequentialFile.Append(id=wxID_PLOTSEQSEL, kind=wx.ITEM_NORMAL,text='Plot selected',
701            help='Plot selected sequential refinement results')
702        self.SequentialFile.Append(id=wxID_AVESEQSEL, kind=wx.ITEM_NORMAL,text='Compute average',
703            help='Compute average for selected parameter')           
704        self.SequentialFile.Append(id=wxID_ORGSEQSEL, kind=wx.ITEM_NORMAL,text='Reorganize',
705            help='Reorganize variables where variables change')
706        self.SequentialPvars = wx.Menu(title='')
707        self.SequentialMenu.Append(menu=self.SequentialPvars, title='Pseudo Vars')
708        self.SequentialPvars.Append(
709            id=wxADDSEQVAR, kind=wx.ITEM_NORMAL,text='Add',
710            help='Add a new pseudo-variable')
711        self.SequentialPvars.Append(
712            id=wxDELSEQVAR, kind=wx.ITEM_NORMAL,text='Delete',
713            help='Delete an existing pseudo-variable')
714        self.SequentialPvars.Append(
715            id=wxEDITSEQVAR, kind=wx.ITEM_NORMAL,text='Edit',
716            help='Edit an existing pseudo-variable')
717
718        self.SequentialPfit = wx.Menu(title='')
719        self.SequentialMenu.Append(menu=self.SequentialPfit, title='Parametric Fit')
720        self.SequentialPfit.Append(
721            id=wxADDPARFIT, kind=wx.ITEM_NORMAL,text='Add equation',
722            help='Add a new equation to minimize')
723        self.SequentialPfit.Append(
724            id=wxCOPYPARFIT, kind=wx.ITEM_NORMAL,text='Copy equation',
725            help='Copy an equation to minimize - edit it next')
726        self.SequentialPfit.Append(
727            id=wxDELPARFIT, kind=wx.ITEM_NORMAL,text='Delete equation',
728            help='Delete an equation for parametric minimization')
729        self.SequentialPfit.Append(
730            id=wxEDITPARFIT, kind=wx.ITEM_NORMAL,text='Edit equation',
731            help='Edit an existing parametric minimization equation')
732        self.SequentialPfit.Append(
733            id=wxDOPARFIT, kind=wx.ITEM_NORMAL,text='Fit to equation(s)',
734            help='Perform a parametric minimization')
735        self.PostfillDataMenu()
736           
737        # PWDR & SASD
738        self.PWDRMenu = wx.MenuBar()
739        self.PrefillDataMenu(self.PWDRMenu,helpType='PWDR Analysis',helpLbl='Powder Fit Error Analysis')
740        self.ErrorAnal = wx.Menu(title='')
741        self.PWDRMenu.Append(menu=self.ErrorAnal,title='Commands')
742        self.ErrorAnal.Append(id=wxID_PWDANALYSIS,kind=wx.ITEM_NORMAL,text='Error Analysis',
743            help='Error analysis on powder pattern')
744        self.ErrorAnal.Append(id=wxID_PWDCOPY,kind=wx.ITEM_NORMAL,text='Copy params',
745            help='Copy of PWDR parameters')
746        self.ErrorAnal.Append(id=wxID_PLOTCTRLCOPY,kind=wx.ITEM_NORMAL,text='Copy plot controls',
747            help='Copy of PWDR plot controls')
748           
749        self.PostfillDataMenu()
750           
751        # HKLF
752        self.HKLFMenu = wx.MenuBar()
753        self.PrefillDataMenu(self.HKLFMenu,helpType='HKLF Analysis',helpLbl='HKLF Fit Error Analysis')
754        self.ErrorAnal = wx.Menu(title='')
755        self.HKLFMenu.Append(menu=self.ErrorAnal,title='Commands')
756        self.ErrorAnal.Append(id=wxID_PWDANALYSIS,kind=wx.ITEM_NORMAL,text='Error Analysis',
757            help='Error analysis on single crystal data')
758        self.ErrorAnal.Append(id=wxID_PWD3DHKLPLOT,kind=wx.ITEM_NORMAL,text='Plot 3D HKLs',
759            help='Plot HKLs from single crystal data in 3D')
760        self.ErrorAnal.Append(id=wxID_3DALLHKLPLOT,kind=wx.ITEM_NORMAL,text='Plot all 3D HKLs',
761            help='Plot HKLs from all single crystal data in 3D')
762        self.ErrorAnal.Append(id=wxID_PWDCOPY,kind=wx.ITEM_NORMAL,text='Copy params',
763            help='Copy of HKLF parameters')
764        self.PostfillDataMenu()
765           
766        # PDR / Limits
767        self.LimitMenu = wx.MenuBar()
768        self.PrefillDataMenu(self.LimitMenu,helpType='Limits')
769        self.LimitEdit = wx.Menu(title='')
770        self.LimitMenu.Append(menu=self.LimitEdit, title='Edit')
771        self.LimitEdit.Append(id=wxID_LIMITCOPY, kind=wx.ITEM_NORMAL,text='Copy',
772            help='Copy limits to other histograms')
773        self.LimitEdit.Append(id=wxID_ADDEXCLREGION, kind=wx.ITEM_NORMAL,text='Add exclude',
774            help='Add excluded region - select a point on plot; drag to adjust')           
775        self.PostfillDataMenu()
776           
777        # PDR / Background
778        self.BackMenu = wx.MenuBar()
779        self.PrefillDataMenu(self.BackMenu,helpType='Background')
780        self.BackEdit = wx.Menu(title='')
781        self.BackMenu.Append(menu=self.BackEdit, title='File')
782        self.BackEdit.Append(id=wxID_BACKCOPY, kind=wx.ITEM_NORMAL,text='Copy',
783            help='Copy background parameters to other histograms')
784        self.BackEdit.Append(id=wxID_BACKFLAGCOPY, kind=wx.ITEM_NORMAL,text='Copy flags',
785            help='Copy background refinement flags to other histograms')
786        self.BackEdit.Append(id=wxID_PEAKSMOVE, kind=wx.ITEM_NORMAL,text='Move peaks',
787            help='Move background peaks to Peak List')
788           
789        self.PostfillDataMenu()
790           
791        # PDR / Instrument Parameters
792        self.InstMenu = wx.MenuBar()
793        self.PrefillDataMenu(self.InstMenu,helpType='Instrument Parameters')
794        self.InstEdit = wx.Menu(title='')
795        self.InstMenu.Append(menu=self.InstEdit, title='Operations')
796        self.InstEdit.Append(help='Calibrate from indexed peaks', 
797            id=wxID_INSTCALIB, kind=wx.ITEM_NORMAL,text='Calibrate')           
798        self.InstEdit.Append(help='Reset instrument profile parameters to default', 
799            id=wxID_INSTPRMRESET, kind=wx.ITEM_NORMAL,text='Reset profile')           
800        self.InstEdit.Append(help='Load instrument profile parameters from file', 
801            id=wxID_INSTLOAD, kind=wx.ITEM_NORMAL,text='Load profile...')           
802        self.InstEdit.Append(help='Save instrument profile parameters to file', 
803            id=wxID_INSTSAVE, kind=wx.ITEM_NORMAL,text='Save profile...')           
804        self.InstEdit.Append(help='Copy instrument profile parameters to other histograms', 
805            id=wxID_INSTCOPY, kind=wx.ITEM_NORMAL,text='Copy')
806        self.InstEdit.Append(id=wxID_INSTFLAGCOPY, kind=wx.ITEM_NORMAL,text='Copy flags',
807            help='Copy instrument parameter refinement flags to other histograms')
808#        self.InstEdit.Append(help='Change radiation type (Ka12 - synch)',
809#            id=wxID_CHANGEWAVETYPE, kind=wx.ITEM_NORMAL,text='Change radiation')
810        self.InstEdit.Append(id=wxID_INST1VAL, kind=wx.ITEM_NORMAL,text='Set one value',
811            help='Set one instrument parameter value across multiple histograms')
812
813        self.PostfillDataMenu()
814       
815        # PDR / Sample Parameters
816        self.SampleMenu = wx.MenuBar()
817        self.PrefillDataMenu(self.SampleMenu,helpType='Sample Parameters')
818        self.SampleEdit = wx.Menu(title='')
819        self.SampleMenu.Append(menu=self.SampleEdit, title='Command')
820        self.SetScale = self.SampleEdit.Append(id=wxID_SETSCALE, kind=wx.ITEM_NORMAL,text='Set scale',
821            help='Set scale by matching to another histogram')
822        self.SampleEdit.Append(id=wxID_SAMPLELOAD, kind=wx.ITEM_NORMAL,text='Load',
823            help='Load sample parameters from file')
824        self.SampleEdit.Append(id=wxID_SAMPLESAVE, kind=wx.ITEM_NORMAL,text='Save',
825            help='Save sample parameters to file')
826        self.SampleEdit.Append(id=wxID_SAMPLECOPY, kind=wx.ITEM_NORMAL,text='Copy',
827            help='Copy refinable and most other sample parameters to other histograms')
828        self.SampleEdit.Append(id=wxID_SAMPLECOPYSOME, kind=wx.ITEM_NORMAL,text='Copy selected...',
829            help='Copy selected sample parameters to other histograms')
830        self.SampleEdit.Append(id=wxID_SAMPLEFLAGCOPY, kind=wx.ITEM_NORMAL,text='Copy flags',
831            help='Copy sample parameter refinement flags to other histograms')
832        self.SampleEdit.Append(id=wxID_SAMPLE1VAL, kind=wx.ITEM_NORMAL,text='Set one value',
833            help='Set one sample parameter value across multiple histograms')
834        self.SampleEdit.Append(id=wxID_ALLSAMPLELOAD, kind=wx.ITEM_NORMAL,text='Load all',
835            help='Load sample parmameters over multiple histograms')
836
837        self.PostfillDataMenu()
838        self.SetScale.Enable(False)
839
840        # PDR / Peak List
841        self.PeakMenu = wx.MenuBar()
842        self.PrefillDataMenu(self.PeakMenu,helpType='Peak List')
843        self.PeakEdit = wx.Menu(title='')
844        self.PeakMenu.Append(menu=self.PeakEdit, title='Peak Fitting')
845        self.AutoSearch = self.PeakEdit.Append(help='Automatic peak search', 
846            id=wxID_AUTOSEARCH, kind=wx.ITEM_NORMAL,text='Auto search')
847        self.UnDo = self.PeakEdit.Append(help='Undo last least squares refinement', 
848            id=wxID_UNDO, kind=wx.ITEM_NORMAL,text='UnDo')
849        self.PeakFit = self.PeakEdit.Append(id=wxID_LSQPEAKFIT, kind=wx.ITEM_NORMAL,text='Peakfit', 
850            help='Peak fitting' )
851        self.PFOneCycle = self.PeakEdit.Append(id=wxID_LSQONECYCLE, kind=wx.ITEM_NORMAL,text='Peakfit one cycle', 
852            help='One cycle of Peak fitting' )
853        self.PeakEdit.Append(id=wxID_RESETSIGGAM, kind=wx.ITEM_NORMAL, 
854            text='Reset sig and gam',help='Reset sigma and gamma to global fit' )
855        self.PeakCopy = self.PeakEdit.Append(help='Copy peaks to other histograms', 
856            id=wxID_PEAKSCOPY, kind=wx.ITEM_NORMAL,text='Peak copy')
857        self.SeqPeakFit = self.PeakEdit.Append(id=wxID_SEQPEAKFIT, kind=wx.ITEM_NORMAL,text='Seq PeakFit', 
858            help='Sequential Peak fitting for all histograms' )
859        self.PeakEdit.Append(id=wxID_CLEARPEAKS, kind=wx.ITEM_NORMAL,text='Clear peaks', 
860            help='Clear the peak list' )
861        self.PostfillDataMenu()
862        self.UnDo.Enable(False)
863        self.PeakFit.Enable(False)
864        self.PFOneCycle.Enable(False)
865        self.AutoSearch.Enable(True)
866       
867        # PDR / Index Peak List
868        self.IndPeaksMenu = wx.MenuBar()
869        self.PrefillDataMenu(self.IndPeaksMenu,helpType='Index Peak List')
870        self.IndPeaksEdit = wx.Menu(title='')
871        self.IndPeaksMenu.Append(menu=self.IndPeaksEdit,title='Operations')
872        self.IndPeaksEdit.Append(help='Load/Reload index peaks from peak list',id=wxID_INDXRELOAD, 
873            kind=wx.ITEM_NORMAL,text='Load/Reload')
874        self.PostfillDataMenu()
875       
876        # PDR / Unit Cells List
877        self.IndexMenu = wx.MenuBar()
878        self.PrefillDataMenu(self.IndexMenu,helpType='Unit Cells List')
879        self.IndexEdit = wx.Menu(title='')
880        self.IndexMenu.Append(menu=self.IndexEdit, title='Cell Index/Refine')
881        self.IndexPeaks = self.IndexEdit.Append(help='', id=wxID_INDEXPEAKS, kind=wx.ITEM_NORMAL,
882            text='Index Cell')
883        self.CopyCell = self.IndexEdit.Append( id=wxID_COPYCELL, kind=wx.ITEM_NORMAL,text='Copy Cell', 
884            help='Copy selected unit cell from indexing to cell refinement fields')
885        self.RefineCell = self.IndexEdit.Append( id=wxID_REFINECELL, kind=wx.ITEM_NORMAL, 
886            text='Refine Cell',help='Refine unit cell parameters from indexed peaks')
887        self.MakeNewPhase = self.IndexEdit.Append( id=wxID_MAKENEWPHASE, kind=wx.ITEM_NORMAL,
888            text='Make new phase',help='Make new phase from selected unit cell')
889        self.PostfillDataMenu()
890        self.IndexPeaks.Enable(False)
891        self.CopyCell.Enable(False)
892        self.RefineCell.Enable(False)
893        self.MakeNewPhase.Enable(False)
894       
895        # PDR / Reflection Lists
896        self.ReflMenu = wx.MenuBar()
897        self.PrefillDataMenu(self.ReflMenu,helpType='Reflection List')
898        self.ReflEdit = wx.Menu(title='')
899        self.ReflMenu.Append(menu=self.ReflEdit, title='Reflection List')
900        self.SelectPhase = self.ReflEdit.Append(help='Select phase for reflection list',id=wxID_SELECTPHASE, 
901            kind=wx.ITEM_NORMAL,text='Select phase')
902        self.ReflEdit.Append(id=wxID_PWDHKLPLOT,kind=wx.ITEM_NORMAL,text='Plot HKLs',
903            help='Plot HKLs from powder pattern')
904        self.ReflEdit.Append(id=wxID_PWD3DHKLPLOT,kind=wx.ITEM_NORMAL,text='Plot 3D HKLs',
905            help='Plot HKLs from powder pattern in 3D')
906        self.PostfillDataMenu()
907       
908        # SASD / Instrument Parameters
909        self.SASDInstMenu = wx.MenuBar()
910        self.PrefillDataMenu(self.SASDInstMenu,helpType='Instrument Parameters')
911        self.SASDInstEdit = wx.Menu(title='')
912        self.SASDInstMenu.Append(menu=self.SASDInstEdit, title='Operations')
913        self.InstEdit.Append(help='Reset instrument profile parameters to default', 
914            id=wxID_INSTPRMRESET, kind=wx.ITEM_NORMAL,text='Reset profile')
915        self.SASDInstEdit.Append(help='Copy instrument profile parameters to other histograms', 
916            id=wxID_INSTCOPY, kind=wx.ITEM_NORMAL,text='Copy')
917        self.PostfillDataMenu()
918       
919        #SASD & REFL/ Substance editor
920        self.SubstanceMenu = wx.MenuBar()
921        self.PrefillDataMenu(self.SubstanceMenu,helpType='Substances')
922        self.SubstanceEdit = wx.Menu(title='')
923        self.SubstanceMenu.Append(menu=self.SubstanceEdit, title='Edit')
924        self.SubstanceEdit.Append(id=wxID_LOADSUBSTANCE, kind=wx.ITEM_NORMAL,text='Load substance',
925            help='Load substance from file')
926        self.SubstanceEdit.Append(id=wxID_ADDSUBSTANCE, kind=wx.ITEM_NORMAL,text='Add substance',
927            help='Add new substance to list')
928        self.SubstanceEdit.Append(id=wxID_COPYSUBSTANCE, kind=wx.ITEM_NORMAL,text='Copy substances',
929            help='Copy substances')
930        self.SubstanceEdit.Append(id=wxID_DELETESUBSTANCE, kind=wx.ITEM_NORMAL,text='Delete substance',
931            help='Delete substance from list')           
932        self.SubstanceEdit.Append(id=wxID_ELEMENTADD, kind=wx.ITEM_NORMAL,text='Add elements',
933            help='Add elements to substance')
934        self.SubstanceEdit.Append(id=wxID_ELEMENTDELETE, kind=wx.ITEM_NORMAL,text='Delete elements',
935            help='Delete elements from substance')
936        self.PostfillDataMenu()
937       
938        # SASD/ Models
939        self.ModelMenu = wx.MenuBar()
940        self.PrefillDataMenu(self.ModelMenu,helpType='Models')
941        self.ModelEdit = wx.Menu(title='')
942        self.ModelMenu.Append(menu=self.ModelEdit, title='Models')
943        self.ModelEdit.Append(id=wxID_MODELADD,kind=wx.ITEM_NORMAL,text='Add',
944            help='Add new term to model')
945        self.ModelEdit.Append(id=wxID_MODELFIT, kind=wx.ITEM_NORMAL,text='Fit',
946            help='Fit model parameters to data')
947        self.SasdUndo = self.ModelEdit.Append(id=wxID_MODELUNDO, kind=wx.ITEM_NORMAL,text='Undo',
948            help='Undo model fit')
949        self.SasdUndo.Enable(False)           
950        self.ModelEdit.Append(id=wxID_MODELFITALL, kind=wx.ITEM_NORMAL,text='Sequential fit',
951            help='Sequential fit of model parameters to all SASD data')
952        self.ModelEdit.Append(id=wxID_MODELCOPY, kind=wx.ITEM_NORMAL,text='Copy',
953            help='Copy model parameters to other histograms')
954        self.ModelEdit.Append(id=wxID_MODELCOPYFLAGS, kind=wx.ITEM_NORMAL,text='Copy flags',
955            help='Copy model refinement flags to other histograms')
956        self.PostfillDataMenu()
957       
958        # IMG / Image Controls
959        self.ImageMenu = wx.MenuBar()
960        self.PrefillDataMenu(self.ImageMenu,helpType='Image Controls')
961        self.ImageEdit = wx.Menu(title='')
962        self.ImageMenu.Append(menu=self.ImageEdit, title='Operations')
963        self.ImageEdit.Append(help='Calibrate detector by fitting to calibrant lines', 
964            id=wxID_IMCALIBRATE, kind=wx.ITEM_NORMAL,text='Calibrate')
965        self.ImageEdit.Append(help='Recalibrate detector by fitting to calibrant lines', 
966            id=wxID_IMRECALIBRATE, kind=wx.ITEM_NORMAL,text='Recalibrate')
967        self.ImageEdit.Append(help='Clear calibration data points and rings',id=wxID_IMCLEARCALIB, 
968            kind=wx.ITEM_NORMAL,text='Clear calibration')
969        self.ImageEdit.Append(help='Integrate selected image',id=wxID_IMINTEGRATE, 
970            kind=wx.ITEM_NORMAL,text='Integrate')
971        self.ImageEdit.Append(help='Integrate all images selected from list',id=wxID_INTEGRATEALL,
972            kind=wx.ITEM_NORMAL,text='Integrate all')
973        self.ImageEdit.Append(help='Copy image controls to other images', 
974            id=wxID_IMCOPYCONTROLS, kind=wx.ITEM_NORMAL,text='Copy Controls')
975        self.ImageEdit.Append(help='Save image controls to file', 
976            id=wxID_IMSAVECONTROLS, kind=wx.ITEM_NORMAL,text='Save Controls')
977        self.ImageEdit.Append(help='Load image controls from file', 
978            id=wxID_IMLOADCONTROLS, kind=wx.ITEM_NORMAL,text='Load Controls')
979        self.PostfillDataMenu()
980           
981        # IMG / Masks
982        self.MaskMenu = wx.MenuBar()
983        self.PrefillDataMenu(self.MaskMenu,helpType='Image Masks')
984        self.MaskEdit = wx.Menu(title='')
985        self.MaskMenu.Append(menu=self.MaskEdit, title='Operations')
986        submenu = wx.Menu()
987        self.MaskEdit.AppendMenu(
988            wx.ID_ANY,'Create new', submenu,
989            help=''
990            )
991        self.MaskEdit.Append(help='Copy mask to other images', 
992            id=wxID_MASKCOPY, kind=wx.ITEM_NORMAL,text='Copy mask')
993        self.MaskEdit.Append(help='Save mask to file', 
994            id=wxID_MASKSAVE, kind=wx.ITEM_NORMAL,text='Save mask')
995        self.MaskEdit.Append(help='Load mask from file', 
996            id=wxID_MASKLOAD, kind=wx.ITEM_NORMAL,text='Load mask')
997        self.MaskEdit.Append(help='Load mask from file; ignore threshold', 
998            id=wxID_MASKLOADNOT, kind=wx.ITEM_NORMAL,text='Load mask w/o threshold')
999        submenu.Append(help='Create an arc mask with mouse input', 
1000            id=wxID_NEWMASKARC, kind=wx.ITEM_NORMAL,text='Arc mask')
1001        submenu.Append(help='Create a frame mask with mouse input', 
1002            id=wxID_NEWMASKFRAME, kind=wx.ITEM_NORMAL,text='Frame mask')
1003        submenu.Append(help='Create a polygon mask with mouse input', 
1004            id=wxID_NEWMASKPOLY, kind=wx.ITEM_NORMAL,text='Polygon mask')
1005        submenu.Append(help='Create a ring mask with mouse input', 
1006            id=wxID_NEWMASKRING, kind=wx.ITEM_NORMAL,text='Ring mask')
1007        submenu.Append(help='Create a spot mask with mouse input', 
1008            id=wxID_NEWMASKSPOT, kind=wx.ITEM_NORMAL,text='Spot mask')
1009        self.PostfillDataMenu()
1010           
1011        # IMG / Stress/Strain
1012        self.StrStaMenu = wx.MenuBar()
1013        self.PrefillDataMenu(self.StrStaMenu,helpType='Stress/Strain')
1014        self.StrStaEdit = wx.Menu(title='')
1015        self.StrStaMenu.Append(menu=self.StrStaEdit, title='Operations')
1016        self.StrStaEdit.Append(help='Append d-zero for one ring', 
1017            id=wxID_APPENDDZERO, kind=wx.ITEM_NORMAL,text='Append d-zero')
1018        self.StrStaEdit.Append(help='Fit stress/strain data', 
1019            id=wxID_STRSTAFIT, kind=wx.ITEM_NORMAL,text='Fit stress/strain')
1020        self.StrStaEdit.Append(help='Update d-zero from ave d-zero',
1021            id=wxID_UPDATEDZERO, kind=wx.ITEM_NORMAL,text='Update d-zero')       
1022        self.StrStaEdit.Append(help='Fit stress/strain data for all images', 
1023            id=wxID_STRSTAALLFIT, kind=wx.ITEM_NORMAL,text='All image fit')
1024        self.StrStaEdit.Append(help='Copy stress/strain data to other images', 
1025            id=wxID_STRSTACOPY, kind=wx.ITEM_NORMAL,text='Copy stress/strain')
1026        self.StrStaEdit.Append(help='Save stress/strain data to file', 
1027            id=wxID_STRSTASAVE, kind=wx.ITEM_NORMAL,text='Save stress/strain')
1028        self.StrStaEdit.Append(help='Load stress/strain data from file', 
1029            id=wxID_STRSTALOAD, kind=wx.ITEM_NORMAL,text='Load stress/strain')
1030        self.StrStaEdit.Append(help='Load sample data from file', 
1031            id=wxID_STRSTSAMPLE, kind=wx.ITEM_NORMAL,text='Load sample data')
1032        self.PostfillDataMenu()
1033           
1034        # PDF / PDF Controls
1035        self.PDFMenu = wx.MenuBar()
1036        self.PrefillDataMenu(self.PDFMenu,helpType='PDF Controls')
1037        self.PDFEdit = wx.Menu(title='')
1038        self.PDFMenu.Append(menu=self.PDFEdit, title='PDF Controls')
1039        self.PDFEdit.Append(help='Add element to sample composition',id=wxID_PDFADDELEMENT, kind=wx.ITEM_NORMAL,
1040            text='Add element')
1041        self.PDFEdit.Append(help='Delete element from sample composition',id=wxID_PDFDELELEMENT, kind=wx.ITEM_NORMAL,
1042            text='Delete element')
1043        self.PDFEdit.Append(help='Copy PDF controls', id=wxID_PDFCOPYCONTROLS, kind=wx.ITEM_NORMAL,
1044            text='Copy controls')
1045        self.PDFEdit.Append(help='Load PDF controls from file',id=wxID_PDFLOADCONTROLS, kind=wx.ITEM_NORMAL,
1046            text='Load Controls')
1047        self.PDFEdit.Append(help='Save PDF controls to file', id=wxID_PDFSAVECONTROLS, kind=wx.ITEM_NORMAL,
1048            text='Save controls')
1049        self.PDFEdit.Append(help='Compute PDF', id=wxID_PDFCOMPUTE, kind=wx.ITEM_NORMAL,
1050            text='Compute PDF')
1051        self.PDFEdit.Append(help='Compute all PDFs', id=wxID_PDFCOMPUTEALL, kind=wx.ITEM_NORMAL,
1052            text='Compute all PDFs')
1053        self.PostfillDataMenu()
1054       
1055        # Phase / General tab
1056        self.DataGeneral = wx.MenuBar()
1057        self.PrefillDataMenu(self.DataGeneral,helpType='General', helpLbl='Phase/General')
1058        self.DataGeneral.Append(menu=wx.Menu(title=''),title='Select tab')
1059        self.GeneralCalc = wx.Menu(title='')
1060        self.DataGeneral.Append(menu=self.GeneralCalc,title='Compute')
1061        self.GeneralCalc.Append(help='Compute Fourier map',id=wxID_FOURCALC, kind=wx.ITEM_NORMAL,
1062            text='Fourier map')
1063        self.GeneralCalc.Append(help='Search Fourier map',id=wxID_FOURSEARCH, kind=wx.ITEM_NORMAL,
1064            text='Search map')
1065        self.GeneralCalc.Append(help='Run charge flipping',id=wxID_CHARGEFLIP, kind=wx.ITEM_NORMAL,
1066            text='Charge flipping')
1067        self.GeneralCalc.Append(help='Run 4D charge flipping',id=wxID_4DCHARGEFLIP, kind=wx.ITEM_NORMAL,
1068            text='4D Charge flipping')
1069        self.GeneralCalc.Enable(wxID_4DCHARGEFLIP,False)   
1070        self.GeneralCalc.Append(help='Clear map',id=wxID_FOURCLEAR, kind=wx.ITEM_NORMAL,
1071            text='Clear map')
1072        self.GeneralCalc.Append(help='Run Monte Carlo - Simulated Annealing',id=wxID_SINGLEMCSA, kind=wx.ITEM_NORMAL,
1073            text='MC/SA')
1074        self.GeneralCalc.Append(help='Run Monte Carlo - Simulated Annealing on multiprocessors',id=wxID_MULTIMCSA, kind=wx.ITEM_NORMAL,
1075            text='Multi MC/SA')            #currently not useful
1076        self.PostfillDataMenu()
1077       
1078        # Phase / Data tab
1079        self.DataMenu = wx.MenuBar()
1080        self.PrefillDataMenu(self.DataMenu,helpType='Data', helpLbl='Phase/Data')
1081        self.DataMenu.Append(menu=wx.Menu(title=''),title='Select tab')
1082        self.DataEdit = wx.Menu(title='')
1083        self.DataMenu.Append(menu=self.DataEdit, title='Edit')
1084        self.DataEdit.Append(id=wxID_DATACOPY, kind=wx.ITEM_NORMAL,text='Copy data',
1085            help='Copy phase data to other histograms')
1086        self.DataEdit.Append(id=wxID_DATACOPYFLAGS, kind=wx.ITEM_NORMAL,text='Copy flags',
1087            help='Copy phase data flags to other histograms')
1088        self.DataEdit.Append(id=wxID_DATASELCOPY, kind=wx.ITEM_NORMAL,text='Copy selected data',
1089            help='Copy selected phase data to other histograms')
1090        self.DataEdit.Append(id=wxID_PWDRADD, kind=wx.ITEM_NORMAL,text='Add powder histograms',
1091            help='Select new powder histograms to be used for this phase')
1092        self.DataEdit.Append(id=wxID_HKLFADD, kind=wx.ITEM_NORMAL,text='Add single crystal histograms',
1093            help='Select new single crystal histograms to be used for this phase')
1094        self.DataEdit.Append(id=wxID_DATADELETE, kind=wx.ITEM_NORMAL,text='Remove histograms',
1095            help='Remove histograms from use for this phase')
1096        self.PostfillDataMenu()
1097           
1098        # Phase / Atoms tab
1099        self.AtomsMenu = wx.MenuBar()
1100        self.PrefillDataMenu(self.AtomsMenu,helpType='Atoms')
1101        self.AtomsMenu.Append(menu=wx.Menu(title=''),title='Select tab')
1102        self.AtomEdit = wx.Menu(title='')
1103        self.AtomCompute = wx.Menu(title='')
1104        self.AtomsMenu.Append(menu=self.AtomEdit, title='Edit')
1105        self.AtomsMenu.Append(menu=self.AtomCompute, title='Compute')
1106        self.AtomEdit.Append(id=wxID_ATOMSEDITADD, kind=wx.ITEM_NORMAL,text='Append atom',
1107            help='Appended as an H atom')
1108        self.AtomEdit.Append(id=wxID_ATOMSVIEWADD, kind=wx.ITEM_NORMAL,text='Append view point',
1109            help='Appended as an H atom')
1110        self.AtomEdit.Append(id=wxID_ATOMSEDITINSERT, kind=wx.ITEM_NORMAL,text='Insert atom',
1111            help='Select atom row to insert before; inserted as an H atom')
1112        self.AtomEdit.Append(id=wxID_ATOMVIEWINSERT, kind=wx.ITEM_NORMAL,text='Insert view point',
1113            help='Select atom row to insert before; inserted as an H atom')
1114        self.AtomEdit.Append(id=wxID_ATOMMOVE, kind=wx.ITEM_NORMAL,text='Move atom to view point',
1115            help='Select single atom to move')
1116        self.AtomEdit.Append(id=wxID_ATOMSEDITDELETE, kind=wx.ITEM_NORMAL,text='Delete atom',
1117            help='Select atoms to delete first')
1118        self.AtomEdit.Append(id=wxID_ATOMSREFINE, kind=wx.ITEM_NORMAL,text='Set atom refinement flags',
1119            help='Select atoms to refine first')
1120        self.AtomEdit.Append(id=wxID_ATOMSMODIFY, kind=wx.ITEM_NORMAL,text='Modify atom parameters',
1121            help='Select atoms to modify first')
1122        self.AtomEdit.Append(id=wxID_ATOMSTRANSFORM, kind=wx.ITEM_NORMAL,text='Transform atoms',
1123            help='Select atoms to transform first')
1124        self.AtomEdit.Append(id=wxID_MAKEMOLECULE, kind=wx.ITEM_NORMAL,text='Assemble molecule',
1125            help='Assemble molecule from scatterd atom positions')
1126        self.AtomEdit.Append(id=wxID_RELOADDRAWATOMS, kind=wx.ITEM_NORMAL,text='Reload draw atoms',
1127            help='Reload atom drawing list')
1128        submenu = wx.Menu()
1129        self.AtomEdit.AppendMenu(wx.ID_ANY, 'Reimport atoms', submenu, 
1130            help='Reimport atoms from file; sequence must match')
1131        # setup a cascade menu for the formats that have been defined
1132        self.ReImportMenuId = {}  # points to readers for each menu entry
1133        for reader in self.G2frame.ImportPhaseReaderlist:
1134            item = submenu.Append(
1135                wx.ID_ANY,help=reader.longFormatName,
1136                kind=wx.ITEM_NORMAL,text='reimport coordinates from '+reader.formatName+' file')
1137            self.ReImportMenuId[item.GetId()] = reader
1138        item = submenu.Append(
1139            wx.ID_ANY,
1140            help='Reimport coordinates, try to determine format from file',
1141            kind=wx.ITEM_NORMAL,
1142            text='guess format from file')
1143        self.ReImportMenuId[item.GetId()] = None # try all readers
1144
1145        self.AtomCompute.Append(id=wxID_ATOMSDISAGL, kind=wx.ITEM_NORMAL,text='Show Distances && Angles',
1146            help='Compute distances & angles for selected atoms')
1147        self.AtomCompute.Append(id=wxID_ATOMSPDISAGL, kind=wx.ITEM_NORMAL,text='Save Distances && Angles',
1148            help='Compute distances & angles for selected atoms')
1149        self.AtomCompute.ISOcalc = self.AtomCompute.Append(
1150            id=wxID_ISODISP, kind=wx.ITEM_NORMAL,
1151            text='Compute ISODISTORT mode values',
1152            help='Compute values of ISODISTORT modes from atom parameters')
1153        self.PostfillDataMenu()
1154       
1155        # Phase / Imcommensurate "waves" tab
1156        self.WavesData = wx.MenuBar()
1157        self.PrefillDataMenu(self.WavesData,helpType='Wave Data', helpLbl='Imcommensurate wave data')
1158        self.WavesData.Append(menu=wx.Menu(title=''),title='Select tab')
1159        self.WavesDataCompute = wx.Menu(title='')
1160        self.WavesData.Append(menu=self.WavesDataCompute,title='Compute')
1161        self.WavesDataCompute.Append(id=wxID_4DMAPCOMPUTE, kind=wx.ITEM_NORMAL,text='Compute 4D map',
1162            help='Compute 4-dimensional map')
1163        self.PostfillDataMenu()
1164                 
1165        # Phase / Draw Options tab
1166        self.DataDrawOptions = wx.MenuBar()
1167        self.PrefillDataMenu(self.DataDrawOptions,helpType='Draw Options', helpLbl='Phase/Draw Options')
1168        self.DataDrawOptions.Append(menu=wx.Menu(title=''),title='Select tab')
1169        self.PostfillDataMenu()
1170       
1171        # Phase / Draw Atoms tab
1172        self.DrawAtomsMenu = wx.MenuBar()
1173        self.PrefillDataMenu(self.DrawAtomsMenu,helpType='Draw Atoms')
1174        self.DrawAtomsMenu.Append(menu=wx.Menu(title=''),title='Select tab')
1175        self.DrawAtomEdit = wx.Menu(title='')
1176        self.DrawAtomCompute = wx.Menu(title='')
1177        self.DrawAtomRestraint = wx.Menu(title='')
1178        self.DrawAtomRigidBody = wx.Menu(title='')
1179        self.DrawAtomsMenu.Append(menu=self.DrawAtomEdit, title='Edit')
1180        self.DrawAtomsMenu.Append(menu=self.DrawAtomCompute,title='Compute')
1181        self.DrawAtomsMenu.Append(menu=self.DrawAtomRestraint, title='Restraints')
1182        self.DrawAtomsMenu.Append(menu=self.DrawAtomRigidBody, title='Rigid body')
1183        self.DrawAtomEdit.Append(id=wxID_DRAWATOMSTYLE, kind=wx.ITEM_NORMAL,text='Atom style',
1184            help='Select atoms first')
1185        self.DrawAtomEdit.Append(id=wxID_DRAWATOMLABEL, kind=wx.ITEM_NORMAL,text='Atom label',
1186            help='Select atoms first')
1187        self.DrawAtomEdit.Append(id=wxID_DRAWATOMCOLOR, kind=wx.ITEM_NORMAL,text='Atom color',
1188            help='Select atoms first')
1189        self.DrawAtomEdit.Append(id=wxID_DRAWATOMRESETCOLOR, kind=wx.ITEM_NORMAL,text='Reset atom colors',
1190            help='Resets all atom colors to defaults')
1191        self.DrawAtomEdit.Append(id=wxID_DRAWVIEWPOINT, kind=wx.ITEM_NORMAL,text='View point',
1192            help='View point is 1st atom selected')
1193        self.DrawAtomEdit.Append(id=wxID_DRAWADDEQUIV, kind=wx.ITEM_NORMAL,text='Add atoms',
1194            help='Add symmetry & cell equivalents to drawing set from selected atoms')
1195        self.DrawAtomEdit.Append(id=wxID_DRAWTRANSFORM, kind=wx.ITEM_NORMAL,text='Transform draw atoms',
1196            help='Transform selected atoms by symmetry & cell translations')
1197        self.DrawAtomEdit.Append(id=wxID_DRAWFILLCOORD, kind=wx.ITEM_NORMAL,text='Fill CN-sphere',
1198            help='Fill coordination sphere for selected atoms')           
1199        self.DrawAtomEdit.Append(id=wxID_DRAWFILLCELL, kind=wx.ITEM_NORMAL,text='Fill unit cell',
1200            help='Fill unit cell with selected atoms')
1201        self.DrawAtomEdit.Append(id=wxID_DRAWDELETE, kind=wx.ITEM_NORMAL,text='Delete atoms',
1202            help='Delete atoms from drawing set')
1203        self.DrawAtomCompute.Append(id=wxID_DRAWDISTVP, kind=wx.ITEM_NORMAL,text='View pt. dist.',
1204            help='Compute distance of selected atoms from view point')   
1205        self.DrawAtomCompute.Append(id=wxID_DRAWDISAGLTOR, kind=wx.ITEM_NORMAL,text='Dist. Ang. Tors.',
1206            help='Compute distance, angle or torsion for 2-4 selected atoms')   
1207        self.DrawAtomCompute.Append(id=wxID_DRAWPLANE, kind=wx.ITEM_NORMAL,text='Best plane',
1208            help='Compute best plane for 4+ selected atoms')   
1209        self.DrawAtomRestraint.Append(id=wxID_DRAWRESTRBOND, kind=wx.ITEM_NORMAL,text='Add bond restraint',
1210            help='Add bond restraint for selected atoms (2)')
1211        self.DrawAtomRestraint.Append(id=wxID_DRAWRESTRANGLE, kind=wx.ITEM_NORMAL,text='Add angle restraint',
1212            help='Add angle restraint for selected atoms (3: one end 1st)')
1213        self.DrawAtomRestraint.Append(id=wxID_DRAWRESTRPLANE, kind=wx.ITEM_NORMAL,text='Add plane restraint',
1214            help='Add plane restraint for selected atoms (4+)')
1215        self.DrawAtomRestraint.Append(id=wxID_DRAWRESTRCHIRAL, kind=wx.ITEM_NORMAL,text='Add chiral restraint',
1216            help='Add chiral restraint for selected atoms (4: center atom 1st)')
1217        self.DrawAtomRigidBody.Append(id=wxID_DRAWDEFINERB, kind=wx.ITEM_NORMAL,text='Define rigid body',
1218            help='Define rigid body with selected atoms')
1219        self.PostfillDataMenu()
1220
1221        # Phase / MCSA tab
1222        self.MCSAMenu = wx.MenuBar()
1223        self.PrefillDataMenu(self.MCSAMenu,helpType='MC/SA')
1224        self.MCSAMenu.Append(menu=wx.Menu(title=''),title='Select tab')
1225        self.MCSAEdit = wx.Menu(title='')
1226        self.MCSAMenu.Append(menu=self.MCSAEdit, title='MC/SA')
1227        self.MCSAEdit.Append(id=wxID_ADDMCSAATOM, kind=wx.ITEM_NORMAL,text='Add atom', 
1228            help='Add single atom to MC/SA model')
1229        self.MCSAEdit.Append(id=wxID_ADDMCSARB, kind=wx.ITEM_NORMAL,text='Add rigid body', 
1230            help='Add rigid body to MC/SA model' )
1231        self.MCSAEdit.Append(id=wxID_CLEARMCSARB, kind=wx.ITEM_NORMAL,text='Clear rigid bodies', 
1232            help='Clear all atoms & rigid bodies from MC/SA model' )
1233        self.MCSAEdit.Append(id=wxID_MOVEMCSA, kind=wx.ITEM_NORMAL,text='Move MC/SA solution', 
1234            help='Move MC/SA solution to atom list' )
1235        self.MCSAEdit.Append(id=wxID_MCSACLEARRESULTS, kind=wx.ITEM_NORMAL,text='Clear results', 
1236            help='Clear table of MC/SA results' )
1237        self.PostfillDataMenu()
1238           
1239        # Phase / Texture tab
1240        self.TextureMenu = wx.MenuBar()
1241        self.PrefillDataMenu(self.TextureMenu,helpType='Texture')
1242        self.TextureMenu.Append(menu=wx.Menu(title=''),title='Select tab')
1243        self.TextureEdit = wx.Menu(title='')
1244        self.TextureMenu.Append(menu=self.TextureEdit, title='Texture')
1245        self.TextureEdit.Append(id=wxID_REFINETEXTURE, kind=wx.ITEM_NORMAL,text='Refine texture', 
1246            help='Refine the texture coefficients from sequential results')
1247        self.TextureEdit.Append(id=wxID_CLEARTEXTURE, kind=wx.ITEM_NORMAL,text='Clear texture', 
1248            help='Clear the texture coefficients' )
1249        self.PostfillDataMenu()
1250           
1251        # Phase / Pawley tab
1252        self.PawleyMenu = wx.MenuBar()
1253        self.PrefillDataMenu(self.PawleyMenu,helpType='Pawley')
1254        self.PawleyMenu.Append(menu=wx.Menu(title=''),title='Select tab')
1255        self.PawleyEdit = wx.Menu(title='')
1256        self.PawleyMenu.Append(menu=self.PawleyEdit,title='Operations')
1257        self.PawleyEdit.Append(id=wxID_PAWLEYLOAD, kind=wx.ITEM_NORMAL,text='Pawley create',
1258            help='Initialize Pawley reflection list')
1259        self.PawleyEdit.Append(id=wxID_PAWLEYESTIMATE, kind=wx.ITEM_NORMAL,text='Pawley estimate',
1260            help='Estimate initial Pawley intensities')
1261        self.PawleyEdit.Append(id=wxID_PAWLEYUPDATE, kind=wx.ITEM_NORMAL,text='Pawley update',
1262            help='Update negative Pawley intensities with -0.5*Fobs and turn off refinemnt')
1263        self.PostfillDataMenu()
1264           
1265        # Phase / Map peaks tab
1266        self.MapPeaksMenu = wx.MenuBar()
1267        self.PrefillDataMenu(self.MapPeaksMenu,helpType='Map peaks')
1268        self.MapPeaksMenu.Append(menu=wx.Menu(title=''),title='Select tab')
1269        self.MapPeaksEdit = wx.Menu(title='')
1270        self.MapPeaksMenu.Append(menu=self.MapPeaksEdit, title='Map peaks')
1271        self.MapPeaksEdit.Append(id=wxID_PEAKSMOVE, kind=wx.ITEM_NORMAL,text='Move peaks', 
1272            help='Move selected peaks to atom list')
1273        self.MapPeaksEdit.Append(id=wxID_PEAKSVIEWPT, kind=wx.ITEM_NORMAL,text='View point',
1274            help='View point is 1st peak selected')
1275        self.MapPeaksEdit.Append(id=wxID_PEAKSDISTVP, kind=wx.ITEM_NORMAL,text='View pt. dist.',
1276            help='Compute distance of selected peaks from view point')   
1277        self.MapPeaksEdit.Append(id=wxID_SHOWBONDS, kind=wx.ITEM_NORMAL,text='Hide bonds',
1278            help='Hide or show bonds between peak positions')   
1279        self.MapPeaksEdit.Append(id=wxID_PEAKSDA, kind=wx.ITEM_NORMAL,text='Calc dist/ang', 
1280            help='Calculate distance or angle for selection')
1281        self.MapPeaksEdit.Append(id=wxID_FINDEQVPEAKS, kind=wx.ITEM_NORMAL,text='Equivalent peaks', 
1282            help='Find equivalent peaks')
1283        self.MapPeaksEdit.Append(id=wxID_PEAKSUNIQUE, kind=wx.ITEM_NORMAL,text='Unique peaks', 
1284            help='Select unique set')
1285        self.MapPeaksEdit.Append(id=wxID_PEAKSDELETE, kind=wx.ITEM_NORMAL,text='Delete peaks', 
1286            help='Delete selected peaks')
1287        self.MapPeaksEdit.Append(id=wxID_PEAKSCLEAR, kind=wx.ITEM_NORMAL,text='Clear peaks', 
1288            help='Clear the map peak list')
1289        self.PostfillDataMenu()
1290
1291        # Phase / Rigid bodies tab
1292        self.RigidBodiesMenu = wx.MenuBar()
1293        self.PrefillDataMenu(self.RigidBodiesMenu,helpType='Rigid bodies')
1294        self.RigidBodiesMenu.Append(menu=wx.Menu(title=''),title='Select tab')
1295        self.RigidBodiesEdit = wx.Menu(title='')
1296        self.RigidBodiesMenu.Append(menu=self.RigidBodiesEdit, title='Edit')
1297        self.RigidBodiesEdit.Append(id=wxID_ASSIGNATMS2RB, kind=wx.ITEM_NORMAL,text='Assign atoms to rigid body',
1298            help='Select & position rigid body in structure of existing atoms')
1299        self.RigidBodiesEdit.Append(id=wxID_AUTOFINDRESRB, kind=wx.ITEM_NORMAL,text='Auto find residues',
1300            help='Auto find of residue RBs in macromolecule')
1301        self.RigidBodiesEdit.Append(id=wxID_COPYRBPARMS, kind=wx.ITEM_NORMAL,text='Copy rigid body parms',
1302            help='Copy rigid body location & TLS parameters')
1303        self.RigidBodiesEdit.Append(id=wxID_GLOBALTHERM, kind=wx.ITEM_NORMAL,text='Global thermal motion',
1304            help='Global setting of residue thermal motion models')
1305        self.RigidBodiesEdit.Append(id=wxID_GLOBALRESREFINE, kind=wx.ITEM_NORMAL,text='Global residue refine',
1306            help='Global setting of residue RB refinement flags')
1307        self.RigidBodiesEdit.Append(id=wxID_RBREMOVEALL, kind=wx.ITEM_NORMAL,text='Remove all rigid bodies',
1308            help='Remove all rigid body assignment for atoms')
1309        self.PostfillDataMenu()
1310    # end of GSAS-II menu definitions
1311       
1312    def _init_ctrls(self, parent,name=None,size=None,pos=None):
1313        wx.Frame.__init__(
1314            self,parent=parent,
1315            #style=wx.DEFAULT_FRAME_STYLE ^ wx.CLOSE_BOX | wx.FRAME_FLOAT_ON_PARENT ,
1316            style=wx.DEFAULT_FRAME_STYLE ^ wx.CLOSE_BOX,
1317            size=size,pos=pos,title='GSAS-II data display')
1318        self._init_menus()
1319        if name:
1320            self.SetLabel(name)
1321        self.Show()
1322       
1323    def __init__(self,parent,frame,data=None,name=None, size=None,pos=None):
1324        self.G2frame = frame
1325        self._init_ctrls(parent,name,size,pos)
1326        self.data = data
1327        clientSize = wx.ClientDisplayRect()
1328        Size = self.GetSize()
1329        xPos = clientSize[2]-Size[0]
1330        self.SetPosition(wx.Point(xPos,clientSize[1]+250))
1331        self.AtomGrid = []
1332        self.selectedRow = 0
1333       
1334    def setSizePosLeft(self,Width):
1335        clientSize = wx.ClientDisplayRect()
1336        Width[1] = min(Width[1],clientSize[2]-300)
1337        Width[0] = max(Width[0],300)
1338        self.SetSize(Width)
1339#        self.SetPosition(wx.Point(clientSize[2]-Width[0],clientSize[1]+250))
1340       
1341    def Clear(self):
1342        self.ClearBackground()
1343        self.DestroyChildren()
1344                   
1345
1346################################################################################
1347#####  Notebook Tree Item editor
1348################################################################################                 
1349def UpdateNotebook(G2frame,data):
1350    '''Called when the data tree notebook entry is selected. Allows for
1351    editing of the text in that tree entry
1352    '''
1353    def OnNoteBook(event):
1354        data = G2frame.dataDisplay.GetValue().split('\n')
1355        G2frame.PatternTree.SetItemPyData(GetPatternTreeItemId(G2frame,G2frame.root,'Notebook'),data)
1356        if 'nt' not in os.name:
1357            G2frame.dataDisplay.AppendText('\n')
1358                   
1359    if G2frame.dataDisplay:
1360        G2frame.dataDisplay.Destroy()
1361    G2frame.dataFrame.SetLabel('Notebook')
1362    G2frame.dataDisplay = wx.TextCtrl(parent=G2frame.dataFrame,size=G2frame.dataFrame.GetClientSize(),
1363        style=wx.TE_MULTILINE|wx.TE_PROCESS_ENTER | wx.TE_DONTWRAP)
1364    G2frame.dataDisplay.Bind(wx.EVT_TEXT_ENTER,OnNoteBook)
1365    G2frame.dataDisplay.Bind(wx.EVT_KILL_FOCUS,OnNoteBook)
1366    for line in data:
1367        G2frame.dataDisplay.AppendText(line+"\n")
1368    G2frame.dataDisplay.AppendText('Notebook entry @ '+time.ctime()+"\n")
1369    G2frame.dataFrame.setSizePosLeft([400,250])
1370           
1371################################################################################
1372#####  Controls Tree Item editor
1373################################################################################           
1374def UpdateControls(G2frame,data):
1375    '''Edit overall GSAS-II controls in main Controls data tree entry
1376    '''
1377    #patch
1378    if 'deriv type' not in data:
1379        data = {}
1380        data['deriv type'] = 'analytic Hessian'
1381        data['min dM/M'] = 0.0001
1382        data['shift factor'] = 1.
1383        data['max cyc'] = 3       
1384        data['F**2'] = False
1385    if 'shift factor' not in data:
1386        data['shift factor'] = 1.
1387    if 'max cyc' not in data:
1388        data['max cyc'] = 3
1389    if 'F**2' not in data:
1390        data['F**2'] = False
1391    if 'Author' not in data:
1392        data['Author'] = 'no name'
1393    if 'FreePrm1' not in data:
1394        data['FreePrm1'] = 'Sample humidity (%)'
1395    if 'FreePrm2' not in data:
1396        data['FreePrm2'] = 'Sample voltage (V)'
1397    if 'FreePrm3' not in data:
1398        data['FreePrm3'] = 'Applied load (MN)'
1399    if 'Copy2Next' not in data:
1400        data['Copy2Next'] = False
1401    if 'Reverse Seq' not in data:
1402        data['Reverse Seq'] = False
1403    if 'UsrReject' not in data:
1404        data['UsrReject'] = {'minF/sig':0,'MinExt':0.01,'MaxDF/F':20.,'MaxD':500.,'MinD':0.05}
1405     
1406   
1407    #end patch
1408
1409    def SeqSizer():
1410       
1411        def OnSelectData(event):
1412            choices = GetPatternTreeDataNames(G2frame,['PWDR','HKLF',])
1413            sel = []
1414            try:
1415                if 'Seq Data' in data:
1416                    for item in data['Seq Data']:
1417                        sel.append(choices.index(item))
1418                    sel = [choices.index(item) for item in data['Seq Data']]
1419            except ValueError:  #data changed somehow - start fresh
1420                sel = []
1421            dlg = G2G.G2MultiChoiceDialog(G2frame.dataFrame, 'Sequential refinement',
1422                'Select dataset to include',choices)
1423            dlg.SetSelections(sel)
1424            names = []
1425            if dlg.ShowModal() == wx.ID_OK:
1426                for sel in dlg.GetSelections():
1427                    names.append(choices[sel])
1428                data['Seq Data'] = names               
1429                G2frame.EnableSeqRefineMenu()
1430            dlg.Destroy()
1431            wx.CallAfter(UpdateControls,G2frame,data)
1432           
1433        def OnReverse(event):
1434            data['Reverse Seq'] = reverseSel.GetValue()
1435           
1436        def OnCopySel(event):
1437            data['Copy2Next'] = copySel.GetValue() 
1438                   
1439        seqSizer = wx.BoxSizer(wx.VERTICAL)
1440        dataSizer = wx.BoxSizer(wx.HORIZONTAL)
1441        dataSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Sequential Refinement: '),0,WACV)
1442        selSeqData = wx.Button(G2frame.dataDisplay,-1,label=' Select data')
1443        selSeqData.Bind(wx.EVT_BUTTON,OnSelectData)
1444        dataSizer.Add(selSeqData,0,WACV)
1445        SeqData = data.get('Seq Data',[])
1446        if not SeqData:
1447            lbl = ' (no data selected)'
1448        else:
1449            lbl = ' ('+str(len(SeqData))+' dataset(s) selected)'
1450
1451        dataSizer.Add(wx.StaticText(G2frame.dataDisplay,label=lbl),0,WACV)
1452        seqSizer.Add(dataSizer,0)
1453        if SeqData:
1454            selSizer = wx.BoxSizer(wx.HORIZONTAL)
1455            reverseSel = wx.CheckBox(G2frame.dataDisplay,-1,label=' Reverse order?')
1456            reverseSel.Bind(wx.EVT_CHECKBOX,OnReverse)
1457            reverseSel.SetValue(data['Reverse Seq'])
1458            selSizer.Add(reverseSel,0,WACV)
1459            copySel =  wx.CheckBox(G2frame.dataDisplay,-1,label=' Copy results to next histogram?')
1460            copySel.Bind(wx.EVT_CHECKBOX,OnCopySel)
1461            copySel.SetValue(data['Copy2Next'])
1462            selSizer.Add(copySel,0,WACV)
1463            seqSizer.Add(selSizer,0)
1464        return seqSizer
1465       
1466    def LSSizer():       
1467       
1468        def OnDerivType(event):
1469            data['deriv type'] = derivSel.GetValue()
1470            derivSel.SetValue(data['deriv type'])
1471            wx.CallAfter(UpdateControls,G2frame,data)
1472           
1473        def OnConvergence(event):
1474            try:
1475                value = max(1.e-9,min(1.0,float(Cnvrg.GetValue())))
1476            except ValueError:
1477                value = 0.0001
1478            data['min dM/M'] = value
1479            Cnvrg.SetValue('%.2g'%(value))
1480           
1481        def OnMaxCycles(event):
1482            data['max cyc'] = int(maxCyc.GetValue())
1483            maxCyc.SetValue(str(data['max cyc']))
1484                       
1485        def OnFactor(event):
1486            try:
1487                value = min(max(float(Factr.GetValue()),0.00001),100.)
1488            except ValueError:
1489                value = 1.0
1490            data['shift factor'] = value
1491            Factr.SetValue('%.5f'%(value))
1492           
1493        def OnFsqRef(event):
1494            data['F**2'] = fsqRef.GetValue()
1495       
1496        def OnUsrRej(event):
1497            Obj = event.GetEventObject()
1498            item,limits = Indx[Obj]
1499            try:
1500                value = min(max(float(Obj.GetValue()),limits[0]),limits[1])
1501            except ValueError:
1502                value = data['UsrReject'][item]
1503            data['UsrReject'][item] = value
1504            Obj.SetValue('%.2f'%(value))
1505
1506        LSSizer = wx.FlexGridSizer(cols=4,vgap=5,hgap=5)
1507        LSSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Refinement derivatives: '),0,WACV)
1508        Choice=['analytic Jacobian','numeric','analytic Hessian']
1509        derivSel = wx.ComboBox(parent=G2frame.dataDisplay,value=data['deriv type'],choices=Choice,
1510            style=wx.CB_READONLY|wx.CB_DROPDOWN)
1511        derivSel.SetValue(data['deriv type'])
1512        derivSel.Bind(wx.EVT_COMBOBOX, OnDerivType)
1513           
1514        LSSizer.Add(derivSel,0,WACV)
1515        LSSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Min delta-M/M: '),0,WACV)
1516        Cnvrg = wx.TextCtrl(G2frame.dataDisplay,-1,value='%.2g'%(data['min dM/M']),style=wx.TE_PROCESS_ENTER)
1517        Cnvrg.Bind(wx.EVT_TEXT_ENTER,OnConvergence)
1518        Cnvrg.Bind(wx.EVT_KILL_FOCUS,OnConvergence)
1519        LSSizer.Add(Cnvrg,0,WACV)
1520        Indx = {}
1521        if 'Hessian' in data['deriv type']:
1522            LSSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Max cycles: '),0,WACV)
1523            Choice = ['0','1','2','3','5','10','15','20']
1524            maxCyc = wx.ComboBox(parent=G2frame.dataDisplay,value=str(data['max cyc']),choices=Choice,
1525                style=wx.CB_READONLY|wx.CB_DROPDOWN)
1526            maxCyc.SetValue(str(data['max cyc']))
1527            maxCyc.Bind(wx.EVT_COMBOBOX, OnMaxCycles)
1528            LSSizer.Add(maxCyc,0,WACV)
1529        else:
1530            LSSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Initial shift factor: '),0,WACV)
1531            Factr = wx.TextCtrl(G2frame.dataDisplay,-1,value='%.5f'%(data['shift factor']),style=wx.TE_PROCESS_ENTER)
1532            Factr.Bind(wx.EVT_TEXT_ENTER,OnFactor)
1533            Factr.Bind(wx.EVT_KILL_FOCUS,OnFactor)
1534            LSSizer.Add(Factr,0,WACV)
1535        if G2frame.Sngl:
1536            userReject = data['UsrReject']
1537            usrRej = {'minF/sig':[' Min obs/sig (0-5): ',[0,5], ],'MinExt':[' Min extinct. (0-.9): ',[0,.9],],
1538                'MaxDF/F':[' Max delt-F/sig (3-1000): ',[3.,1000.],],'MaxD':[' Max d-spacing (3-500): ',[3,500],],
1539                'MinD':[' Min d-spacing (0.1-1.0): ',[0.1,1.0],]}
1540
1541            fsqRef = wx.CheckBox(G2frame.dataDisplay,-1,label='Refine HKLF as F^2? ')
1542            fsqRef.SetValue(data['F**2'])
1543            fsqRef.Bind(wx.EVT_CHECKBOX,OnFsqRef)
1544            LSSizer.Add(fsqRef,0,WACV)
1545            LSSizer.Add((1,0),)
1546            for item in usrRej:
1547                LSSizer.Add(wx.StaticText(G2frame.dataDisplay,-1,label=usrRej[item][0]),0,WACV)
1548                usrrej = wx.TextCtrl(G2frame.dataDisplay,-1,value='%.2f'%(userReject[item]),style=wx.TE_PROCESS_ENTER)
1549                Indx[usrrej] = [item,usrRej[item][1]]
1550                usrrej.Bind(wx.EVT_TEXT_ENTER,OnUsrRej)
1551                usrrej.Bind(wx.EVT_KILL_FOCUS,OnUsrRej)
1552                LSSizer.Add(usrrej,0,WACV)
1553        return LSSizer
1554       
1555    def AuthSizer():
1556
1557        def OnAuthor(event):
1558            data['Author'] = auth.GetValue()
1559
1560        Author = data['Author']
1561        authSizer = wx.BoxSizer(wx.HORIZONTAL)
1562        authSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' CIF Author (last, first):'),0,WACV)
1563        auth = wx.TextCtrl(G2frame.dataDisplay,-1,value=Author,style=wx.TE_PROCESS_ENTER)
1564        auth.Bind(wx.EVT_TEXT_ENTER,OnAuthor)
1565        auth.Bind(wx.EVT_KILL_FOCUS,OnAuthor)
1566        authSizer.Add(auth,0,WACV)
1567        return authSizer
1568       
1569       
1570    if G2frame.dataDisplay:
1571        G2frame.dataDisplay.Destroy()
1572    if not G2frame.dataFrame.GetStatusBar():
1573        Status = G2frame.dataFrame.CreateStatusBar()
1574        Status.SetStatusText('')
1575    G2frame.dataFrame.SetLabel('Controls')
1576    G2frame.dataDisplay = wx.Panel(G2frame.dataFrame)
1577    SetDataMenuBar(G2frame,G2frame.dataFrame.ControlsMenu)
1578    mainSizer = wx.BoxSizer(wx.VERTICAL)
1579    mainSizer.Add((5,5),0)
1580    mainSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Refinement Controls:'),0,WACV)   
1581    mainSizer.Add(LSSizer())
1582    mainSizer.Add((5,5),0)
1583    mainSizer.Add(SeqSizer())
1584    mainSizer.Add((5,5),0)
1585    mainSizer.Add(AuthSizer())
1586    mainSizer.Add((5,5),0)
1587       
1588    mainSizer.Layout()   
1589    G2frame.dataDisplay.SetSizer(mainSizer)
1590    G2frame.dataDisplay.SetSize(mainSizer.Fit(G2frame.dataFrame))
1591    G2frame.dataFrame.setSizePosLeft(mainSizer.Fit(G2frame.dataFrame))
1592     
1593################################################################################
1594#####  Comments
1595################################################################################           
1596       
1597def UpdateComments(G2frame,data):                   
1598
1599    if G2frame.dataDisplay:
1600        G2frame.dataDisplay.Destroy()
1601    G2frame.dataFrame.SetLabel('Comments')
1602    G2frame.dataDisplay = wx.TextCtrl(parent=G2frame.dataFrame,size=G2frame.dataFrame.GetClientSize(),
1603        style=wx.TE_MULTILINE|wx.TE_READONLY|wx.TE_DONTWRAP)
1604    for line in data:
1605        G2frame.dataDisplay.AppendText(line+'\n')
1606    G2frame.dataFrame.setSizePosLeft([400,250])
1607           
1608################################################################################
1609#####  Display of Sequential Results
1610################################################################################           
1611       
1612def UpdateSeqResults(G2frame,data,prevSize=None):
1613    """
1614    Called when the Sequential Results data tree entry is selected
1615    to show results from a sequential refinement.
1616   
1617    :param wx.Frame G2frame: main GSAS-II data tree windows
1618
1619    :param dict data: a dictionary containing the following items: 
1620
1621            * 'histNames' - list of histogram names in order as processed by Sequential Refinement
1622            * 'varyList' - list of variables - identical over all refinements in sequence
1623              note that this is the original list of variables, prior to processing
1624              constraints.
1625            * 'variableLabels' -- a dict of labels to be applied to each parameter
1626              (this is created as an empty dict if not present in data).
1627            * keyed by histName - dictionaries for all data sets processed, which contains:
1628
1629              * 'variables'- result[0] from leastsq call
1630              * 'varyList' - list of variables passed to leastsq call (not same as above)
1631              * 'sig' - esds for variables
1632              * 'covMatrix' - covariance matrix from individual refinement
1633              * 'title' - histogram name; same as dict item name
1634              * 'newAtomDict' - new atom parameters after shifts applied
1635              * 'newCellDict' - refined cell parameters after shifts to A0-A5 from Dij terms applied'
1636    """
1637
1638    def GetSampleParms():
1639        '''Make a dictionary of the sample parameters are not the same over the
1640        refinement series.
1641        '''
1642        if 'IMG' in histNames[0]:
1643            sampleParmDict = {'Sample load':[],}
1644        else:
1645            sampleParmDict = {'Temperature':[],'Pressure':[],'Time':[],
1646                'FreePrm1':[],'FreePrm2':[],'FreePrm3':[],'Omega':[],
1647                'Chi':[],'Phi':[],'Azimuth':[],}
1648        Controls = G2frame.PatternTree.GetItemPyData(
1649            GetPatternTreeItemId(G2frame,G2frame.root, 'Controls'))
1650        sampleParm = {}
1651        for name in histNames:
1652            if 'IMG' in name:
1653                for item in sampleParmDict:
1654                    sampleParmDict[item].append(data[name]['parmDict'].get(item,0))
1655            else:
1656                Id = GetPatternTreeItemId(G2frame,G2frame.root,name)
1657                sampleData = G2frame.PatternTree.GetItemPyData(GetPatternTreeItemId(G2frame,Id,'Sample Parameters'))
1658                for item in sampleParmDict:
1659                    sampleParmDict[item].append(sampleData.get(item,0))
1660        for item in sampleParmDict:
1661            frstValue = sampleParmDict[item][0]
1662            if np.any(np.array(sampleParmDict[item])-frstValue):
1663                if item.startswith('FreePrm'):
1664                    sampleParm[Controls[item]] = sampleParmDict[item]
1665                else:
1666                    sampleParm[item] = sampleParmDict[item]
1667        return sampleParm
1668
1669    def GetColumnInfo(col):
1670        '''returns column label, lists of values and errors (or None) for each column in the table
1671        for plotting. The column label is reformatted from Unicode to MatPlotLib encoding
1672        '''
1673        colName = G2frame.SeqTable.GetColLabelValue(col)
1674        plotName = variableLabels.get(colName,colName)
1675        plotName = plotSpCharFix(plotName)
1676        return plotName,colList[col],colSigs[col]
1677           
1678    def PlotSelect(event):
1679        'Plots a row (covariance) or column on double-click'
1680        cols = G2frame.dataDisplay.GetSelectedCols()
1681        rows = G2frame.dataDisplay.GetSelectedRows()
1682        if cols:
1683            G2plt.PlotSelectedSequence(G2frame,cols,GetColumnInfo,SelectXaxis)
1684        elif rows:
1685            name = histNames[rows[0]]       #only does 1st one selected
1686            G2plt.PlotCovariance(G2frame,data[name])
1687        else:
1688            G2frame.ErrorDialog(
1689                'Select row or columns',
1690                'Nothing selected in table. Click on column or row label(s) to plot. N.B. Grid selection can be a bit funky.'
1691                )
1692           
1693    def OnPlotSelSeq(event):
1694        'plot the selected columns or row from menu command'
1695        cols = sorted(G2frame.dataDisplay.GetSelectedCols()) # ignore selection order
1696        rows = G2frame.dataDisplay.GetSelectedRows()
1697        if cols:
1698            G2plt.PlotSelectedSequence(G2frame,cols,GetColumnInfo,SelectXaxis)
1699        elif rows:
1700            name = histNames[rows[0]]       #only does 1st one selected
1701            G2plt.PlotCovariance(G2frame,data[name])
1702        else:
1703            G2frame.ErrorDialog(
1704                'Select columns',
1705                'No columns or rows selected in table. Click on row or column labels to select fields for plotting.'
1706                )
1707               
1708    def OnAveSelSeq(event):
1709        'average the selected columns from menu command'
1710        cols = sorted(G2frame.dataDisplay.GetSelectedCols()) # ignore selection order
1711        if cols:
1712            for col in cols:
1713                ave = np.mean(GetColumnInfo(col)[1])
1714                sig = np.std(GetColumnInfo(col)[1])
1715                print ' Average for '+G2frame.SeqTable.GetColLabelValue(col)+': '+'%.6g'%(ave)+' +/- '+'%.6g'%(sig)
1716        else:
1717            G2frame.ErrorDialog(
1718                'Select columns',
1719                'No columns selected in table. Click on column labels to select fields for averaging.'
1720                )
1721               
1722    def OnRenameSelSeq(event):
1723        cols = sorted(G2frame.dataDisplay.GetSelectedCols()) # ignore selection order
1724        colNames = [G2frame.SeqTable.GetColLabelValue(c) for c in cols]
1725        newNames = colNames[:]
1726        for i,name in enumerate(colNames):
1727            if name in variableLabels:
1728                newNames[i] = variableLabels[name]
1729        if not cols:
1730            G2frame.ErrorDialog('Select columns',
1731                'No columns selected in table. Click on column labels to select fields for rename.')
1732            return
1733        dlg = G2G.MultiStringDialog(G2frame.dataDisplay,'Set column names',colNames,newNames)
1734        if dlg.Show():
1735            newNames = dlg.GetValues()           
1736            variableLabels.update(dict(zip(colNames,newNames)))
1737        data['variableLabels'] = variableLabels
1738        dlg.Destroy()
1739        UpdateSeqResults(G2frame,data,G2frame.dataDisplay.GetSize()) # redisplay variables
1740        G2plt.PlotSelectedSequence(G2frame,cols,GetColumnInfo,SelectXaxis)
1741           
1742    def OnReOrgSelSeq(event):
1743        'Reorder the columns'
1744        G2G.GetItemOrder(G2frame,VaryListChanges,vallookup,posdict)   
1745        UpdateSeqResults(G2frame,data,G2frame.dataDisplay.GetSize()) # redisplay variables
1746
1747    def OnSaveSelSeqCSV(event):
1748        'export the selected columns to a .csv file from menu command'
1749        OnSaveSelSeq(event,csv=True)
1750       
1751    def OnSaveSeqCSV(event):
1752        'export all columns to a .csv file from menu command'
1753        OnSaveSelSeq(event,csv=True,allcols=True)
1754       
1755    def OnSaveSelSeq(event,csv=False,allcols=False):
1756        'export the selected columns to a .txt or .csv file from menu command'
1757        def WriteCSV():
1758            def WriteList(headerItems):
1759                line = ''
1760                for lbl in headerItems:
1761                    if line: line += ','
1762                    line += '"'+lbl+'"'
1763                return line
1764            head = ['name']
1765            for col in cols:
1766                item = G2frame.SeqTable.GetColLabelValue(col)
1767                # get rid of labels that have Unicode characters
1768                if not all([ord(c) < 128 and ord(c) != 0 for c in item]): item = '?'
1769                if col in havesig:
1770                    head += [item,'esd-'+item]
1771                else:
1772                    head += [item]
1773            SeqFile.write(WriteList(head)+'\n')
1774            for row,name in enumerate(saveNames):
1775                line = '"'+saveNames[row]+'"'
1776                for col in cols:
1777                    if col in havesig:
1778                        line += ','+str(saveData[col][row])+','+str(saveSigs[col][row])
1779                    else:
1780                        line += ','+str(saveData[col][row])
1781                SeqFile.write(line+'\n')
1782        def WriteSeq():
1783            lenName = len(saveNames[0])
1784            line = %s  '%('name'.center(lenName))
1785            for col in cols:
1786                item = G2frame.SeqTable.GetColLabelValue(col)
1787                if col in havesig:
1788                    line += ' %12s %12s '%(item.center(12),'esd'.center(12))
1789                else:
1790                    line += ' %12s '%(item.center(12))
1791            SeqFile.write(line+'\n')
1792            for row,name in enumerate(saveNames):
1793                line = " '%s' "%(saveNames[row])
1794                for col in cols:
1795                    if col in havesig:
1796                        line += ' %12.6f %12.6f '%(saveData[col][row],saveSigs[col][row])
1797                    else:
1798                        line += ' %12.6f '%saveData[col][row]
1799                SeqFile.write(line+'\n')
1800
1801        # start of OnSaveSelSeq code
1802        if allcols:
1803            cols = range(G2frame.SeqTable.GetNumberCols())
1804        else:
1805            cols = sorted(G2frame.dataDisplay.GetSelectedCols()) # ignore selection order
1806        nrows = G2frame.SeqTable.GetNumberRows()
1807        if not cols:
1808            G2frame.ErrorDialog('Select columns',
1809                             'No columns selected in table. Click on column labels to select fields for output.')
1810            return
1811        saveNames = [G2frame.SeqTable.GetRowLabelValue(r) for r in range(nrows)]
1812        saveData = {}
1813        saveSigs = {}
1814        havesig = []
1815        for col in cols:
1816            name,vals,sigs = GetColumnInfo(col)
1817            saveData[col] = vals
1818            if sigs:
1819                havesig.append(col)
1820                saveSigs[col] = sigs
1821        if csv:
1822            wild = 'CSV output file (*.csv)|*.csv'
1823        else:
1824            wild = 'Text output file (*.txt)|*.txt'
1825        dlg = wx.FileDialog(
1826            G2frame,
1827            'Choose text output file for your selection', '.', '', 
1828            wild,wx.FD_SAVE|wx.FD_OVERWRITE_PROMPT|wx.CHANGE_DIR)
1829        try:
1830            if dlg.ShowModal() == wx.ID_OK:
1831                SeqTextFile = dlg.GetPath()
1832                SeqTextFile = G2IO.FileDlgFixExt(dlg,SeqTextFile) 
1833                SeqFile = open(SeqTextFile,'w')
1834                if csv:
1835                    WriteCSV()
1836                else:
1837                    WriteSeq()
1838                SeqFile.close()
1839        finally:
1840            dlg.Destroy()
1841               
1842    def striphist(var,insChar=''):
1843        'strip a histogram number from a var name'
1844        sv = var.split(':')
1845        if len(sv) <= 1: return var
1846        if sv[1]:
1847            sv[1] = insChar
1848        return ':'.join(sv)
1849       
1850    def plotSpCharFix(lbl):
1851        'Change selected unicode characters to their matplotlib equivalent'
1852        for u,p in [
1853            (u'\u03B1',r'$\alpha$'),
1854            (u'\u03B2',r'$\beta$'),
1855            (u'\u03B3',r'$\gamma$'),
1856            (u'\u0394\u03C7',r'$\Delta\chi$'),
1857            ]:
1858            lbl = lbl.replace(u,p)
1859        return lbl
1860   
1861    def SelectXaxis():
1862        'returns a selected column number (or None) as the X-axis selection'
1863        ncols = G2frame.SeqTable.GetNumberCols()
1864        colNames = [G2frame.SeqTable.GetColLabelValue(r) for r in range(ncols)]
1865        dlg = G2G.G2SingleChoiceDialog(
1866            G2frame.dataDisplay,
1867            'Select x-axis parameter for plot or Cancel for sequence number',
1868            'Select X-axis',
1869            colNames)
1870        try:
1871            if dlg.ShowModal() == wx.ID_OK:
1872                col = dlg.GetSelection()
1873            else:
1874                col = None
1875        finally:
1876            dlg.Destroy()
1877        return col
1878   
1879    def EnablePseudoVarMenus():
1880        'Enables or disables the PseudoVar menu items that require existing defs'
1881        if Controls['SeqPseudoVars']:
1882            val = True
1883        else:
1884            val = False
1885        G2frame.dataFrame.SequentialPvars.Enable(wxDELSEQVAR,val)
1886        G2frame.dataFrame.SequentialPvars.Enable(wxEDITSEQVAR,val)
1887
1888    def DelPseudoVar(event):
1889        'Ask the user to select a pseudo var expression to delete'
1890        choices = Controls['SeqPseudoVars'].keys()
1891        selected = G2G.ItemSelector(
1892            choices,G2frame.dataFrame,
1893            multiple=True,
1894            title='Select expressions to remove',
1895            header='Delete expression')
1896        if selected is None: return
1897        for item in selected:
1898            del Controls['SeqPseudoVars'][choices[item]]
1899        if selected:
1900            UpdateSeqResults(G2frame,data,G2frame.dataDisplay.GetSize()) # redisplay variables
1901
1902    def EditPseudoVar(event):
1903        'Edit an existing pseudo var expression'
1904        choices = Controls['SeqPseudoVars'].keys()
1905        if len(choices) == 1:
1906            selected = 0
1907        else:
1908            selected = G2G.ItemSelector(
1909                choices,G2frame.dataFrame,
1910                multiple=False,
1911                title='Select an expression to edit',
1912                header='Edit expression')
1913        if selected is not None:
1914            dlg = G2exG.ExpressionDialog(
1915                G2frame.dataDisplay,PSvarDict,
1916                Controls['SeqPseudoVars'][choices[selected]],
1917                header="Edit the PseudoVar expression",
1918                VarLabel="PseudoVar #"+str(selected+1),
1919                fit=False)
1920            newobj = dlg.Show(True)
1921            if newobj:
1922                calcobj = G2obj.ExpressionCalcObj(newobj)
1923                del Controls['SeqPseudoVars'][choices[selected]]
1924                Controls['SeqPseudoVars'][calcobj.eObj.expression] = newobj
1925                UpdateSeqResults(G2frame,data,G2frame.dataDisplay.GetSize()) # redisplay variables
1926       
1927    def AddNewPseudoVar(event):
1928        'Create a new pseudo var expression'
1929        dlg = G2exG.ExpressionDialog(
1930            G2frame.dataDisplay,PSvarDict,
1931            header='Enter an expression for a PseudoVar here',
1932            VarLabel = "New PseudoVar",
1933            fit=False)
1934        obj = dlg.Show(True)
1935        dlg.Destroy()
1936        if obj:
1937            calcobj = G2obj.ExpressionCalcObj(obj)
1938            Controls['SeqPseudoVars'][calcobj.eObj.expression] = obj
1939            UpdateSeqResults(G2frame,data,G2frame.dataDisplay.GetSize()) # redisplay variables
1940
1941    def UpdateParmDict(parmDict):
1942        '''generate the atom positions and the direct & reciprocal cell values,
1943        because they might be needed to evaluate the pseudovar
1944        '''
1945        Ddict = dict(zip(['D11','D22','D33','D12','D13','D23'],
1946                         ['A'+str(i) for i in range(6)])
1947                     )
1948        delList = []
1949        phaselist = []
1950        for item in parmDict: 
1951            if ':' not in item: continue
1952            key = item.split(':')
1953            if len(key) < 3: continue
1954            # remove the dA[xyz] terms, they would only bring confusion
1955            if key[2].startswith('dA'):
1956                delList.append(item)
1957            # compute and update the corrected reciprocal cell terms using the Dij values
1958            elif key[2] in Ddict:
1959                if key[0] not in phaselist: phaselist.append(key[0])
1960                akey = key[0]+'::'+Ddict[key[2]]
1961                parmDict[akey] -= parmDict[item]
1962                delList.append(item)
1963        for item in delList:
1964            del parmDict[item]               
1965        for i in phaselist:
1966            pId = int(i)
1967            # apply cell symmetry
1968            A,zeros = G2stIO.cellFill(str(pId)+'::',SGdata[pId],parmDict,zeroDict[pId])
1969            # convert to direct cell & add the unique terms to the dictionary
1970            for i,val in enumerate(G2lat.A2cell(A)):
1971                if i in uniqCellIndx[pId]:
1972                    lbl = str(pId)+'::'+cellUlbl[i]
1973                    parmDict[lbl] = val
1974            lbl = str(pId)+'::'+'vol'
1975            parmDict[lbl] = G2lat.calc_V(A)
1976        return parmDict
1977
1978    def EvalPSvarDeriv(calcobj,parmDict,sampleDict,var,ESD):
1979        '''Evaluate an expression derivative with respect to a
1980        GSAS-II variable name.
1981
1982        Note this likely could be faster if the loop over calcobjs were done
1983        inside after the Dict was created.
1984        '''
1985        step = ESD/10
1986        Ddict = dict(zip(['D11','D22','D33','D12','D13','D23'],
1987                         ['A'+str(i) for i in range(6)])
1988                     )
1989        results = []
1990        phaselist = []
1991        VparmDict = sampleDict.copy()
1992        for incr in step,-step:
1993            VparmDict.update(parmDict.copy())           
1994            # as saved, the parmDict has updated 'A[xyz]' values, but 'dA[xyz]'
1995            # values are not zeroed: fix that!
1996            VparmDict.update({item:0.0 for item in parmDict if 'dA' in item})
1997            VparmDict[var] += incr
1998            G2mv.Dict2Map(VparmDict,[]) # apply constraints
1999            # generate the atom positions and the direct & reciprocal cell values now, because they might
2000            # needed to evaluate the pseudovar
2001            for item in VparmDict:
2002                if item in sampleDict:
2003                    continue 
2004                if ':' not in item: continue
2005                key = item.split(':')
2006                if len(key) < 3: continue
2007                # apply any new shifts to atom positions
2008                if key[2].startswith('dA'):
2009                    VparmDict[''.join(item.split('d'))] += VparmDict[item]
2010                    VparmDict[item] = 0.0
2011                # compute and update the corrected reciprocal cell terms using the Dij values
2012                if key[2] in Ddict:
2013                    if key[0] not in phaselist: phaselist.append(key[0])
2014                    akey = key[0]+'::'+Ddict[key[2]]
2015                    VparmDict[akey] -= VparmDict[item]
2016            for i in phaselist:
2017                pId = int(i)
2018                # apply cell symmetry
2019                A,zeros = G2stIO.cellFill(str(pId)+'::',SGdata[pId],VparmDict,zeroDict[pId])
2020                # convert to direct cell & add the unique terms to the dictionary
2021                for i,val in enumerate(G2lat.A2cell(A)):
2022                    if i in uniqCellIndx[pId]:
2023                        lbl = str(pId)+'::'+cellUlbl[i]
2024                        VparmDict[lbl] = val
2025                lbl = str(pId)+'::'+'vol'
2026                VparmDict[lbl] = G2lat.calc_V(A)
2027            # dict should be fully updated, use it & calculate
2028            calcobj.SetupCalc(VparmDict)
2029            results.append(calcobj.EvalExpression())
2030        return (results[0] - results[1]) / (2.*step)
2031       
2032    def EnableParFitEqMenus():
2033        'Enables or disables the Parametric Fit menu items that require existing defs'
2034        if Controls['SeqParFitEqList']:
2035            val = True
2036        else:
2037            val = False
2038        G2frame.dataFrame.SequentialPfit.Enable(wxDELPARFIT,val)
2039        G2frame.dataFrame.SequentialPfit.Enable(wxEDITPARFIT,val)
2040        G2frame.dataFrame.SequentialPfit.Enable(wxDOPARFIT,val)
2041
2042    def ParEqEval(Values,calcObjList,varyList):
2043        '''Evaluate the parametric expression(s)
2044        :param list Values: a list of values for each variable parameter
2045        :param list calcObjList: a list of :class:`GSASIIobj.ExpressionCalcObj`
2046          expression objects to evaluate
2047        :param list varyList: a list of variable names for each value in Values
2048        '''
2049        result = []
2050        for calcobj in calcObjList:
2051            calcobj.UpdateVars(varyList,Values)
2052            result.append((calcobj.depVal-calcobj.EvalExpression())/calcobj.depSig)
2053        return result
2054
2055    def DoParEqFit(event,eqObj=None):
2056        'Parametric fit minimizer'
2057        varyValueDict = {} # dict of variables and their initial values
2058        calcObjList = [] # expression objects, ready to go for each data point
2059        if eqObj is not None:
2060            eqObjList = [eqObj,]
2061        else:
2062            eqObjList = Controls['SeqParFitEqList']
2063        UseFlags = G2frame.SeqTable.GetColValues(0)         
2064        for obj in eqObjList:
2065            expr = obj.expression
2066            # assemble refined vars for this equation
2067            varyValueDict.update({var:val for var,val in obj.GetVariedVarVal()})
2068            # lookup dependent var position
2069            depVar = obj.GetDepVar()
2070            if depVar in colLabels:
2071                indx = colLabels.index(depVar)
2072            else:
2073                raise Exception('Dependent variable '+depVar+' not found')
2074            # assemble a list of the independent variables
2075            indepVars = obj.GetIndependentVars()
2076            # loop over each datapoint
2077            for j,row in enumerate(zip(*colList)):
2078                if not UseFlags[j]: continue
2079                # assemble equations to fit
2080                calcobj = G2obj.ExpressionCalcObj(obj)
2081                # prepare a dict of needed independent vars for this expression
2082                indepVarDict = {var:row[i] for i,var in enumerate(colLabels) if var in indepVars}
2083                calcobj.SetupCalc(indepVarDict)               
2084                # values and sigs for current value of dependent var
2085                calcobj.depVal = row[indx]
2086                calcobj.depSig = colSigs[indx][j]
2087                calcObjList.append(calcobj)
2088        # varied parameters
2089        varyList = varyValueDict.keys()
2090        values = varyValues = [varyValueDict[key] for key in varyList]
2091        if not varyList:
2092            print 'no variables to refine!'
2093            return
2094        try:
2095            result = so.leastsq(ParEqEval,varyValues,full_output=True,   #ftol=Ftol,
2096                                args=(calcObjList,varyList)
2097                                )
2098            values = result[0]
2099            covar = result[1]
2100            if covar is None:
2101                raise Exception
2102            esdDict = {}
2103            for i,avar in enumerate(varyList):
2104                esdDict[avar] = np.sqrt(covar[i,i])
2105        except:
2106            print('====> Fit failed')
2107            return
2108        print('==== Fit Results ====')
2109        for obj in eqObjList:
2110            obj.UpdateVariedVars(varyList,values)
2111            ind = '      '
2112            print('  '+obj.GetDepVar()+' = '+obj.expression)
2113            for var in obj.assgnVars:
2114                print(ind+var+' = '+obj.assgnVars[var])
2115            for var in obj.freeVars:
2116                avar = "::"+obj.freeVars[var][0]
2117                val = obj.freeVars[var][1]
2118                if obj.freeVars[var][2]:
2119                    print(ind+var+' = '+avar + " = " + G2mth.ValEsd(val,esdDict[avar]))
2120                else:
2121                    print(ind+var+' = '+avar + " =" + G2mth.ValEsd(val,0))
2122        # create a plot for each parametric variable
2123        for fitnum,obj in enumerate(eqObjList):
2124            calcobj = G2obj.ExpressionCalcObj(obj)
2125            # lookup dependent var position
2126            indx = colLabels.index(obj.GetDepVar())
2127            # assemble a list of the independent variables
2128            indepVars = obj.GetIndependentVars()           
2129            # loop over each datapoint
2130            fitvals = []
2131            for j,row in enumerate(zip(*colList)):
2132                calcobj.SetupCalc(
2133                    {var:row[i] for i,var in enumerate(colLabels) if var in indepVars}
2134                    )
2135                fitvals.append(calcobj.EvalExpression())
2136            G2plt.PlotSelectedSequence(
2137                G2frame,[indx],GetColumnInfo,SelectXaxis,
2138                fitnum,fitvals)
2139
2140    def SingleParEqFit(eqObj):
2141        DoParEqFit(None,eqObj)
2142
2143    def DelParFitEq(event):
2144        'Ask the user to select function to delete'
2145        txtlst = [obj.GetDepVar()+' = '+obj.expression for obj in Controls['SeqParFitEqList']]
2146        selected = G2G.ItemSelector(
2147            txtlst,G2frame.dataFrame,
2148            multiple=True,
2149            title='Select a parametric equation(s) to remove',
2150            header='Delete equation')
2151        if selected is None: return
2152        Controls['SeqParFitEqList'] = [obj for i,obj in enumerate(Controls['SeqParFitEqList']) if i not in selected]
2153        EnableParFitEqMenus()
2154        if Controls['SeqParFitEqList']: DoParEqFit(event)
2155       
2156    def EditParFitEq(event):
2157        'Edit an existing parametric equation'
2158        txtlst = [obj.GetDepVar()+' = '+obj.expression for obj in Controls['SeqParFitEqList']]
2159        if len(txtlst) == 1:
2160            selected = 0
2161        else:
2162            selected = G2G.ItemSelector(
2163                txtlst,G2frame.dataFrame,
2164                multiple=False,
2165                title='Select a parametric equation to edit',
2166                header='Edit equation')
2167        if selected is not None:
2168            dlg = G2exG.ExpressionDialog(
2169                G2frame.dataDisplay,indepVarDict,
2170                Controls['SeqParFitEqList'][selected],
2171                depVarDict=depVarDict,
2172                header="Edit the formula for this minimization function",
2173                ExtraButton=['Fit',SingleParEqFit])
2174            newobj = dlg.Show(True)
2175            if newobj:
2176                calcobj = G2obj.ExpressionCalcObj(newobj)
2177                Controls['SeqParFitEqList'][selected] = newobj
2178                EnableParFitEqMenus()
2179            if Controls['SeqParFitEqList']: DoParEqFit(event)
2180
2181    def AddNewParFitEq(event):
2182        'Create a new parametric equation to be fit to sequential results'
2183
2184        # compile the variable names used in previous freevars to avoid accidental name collisions
2185        usedvarlist = []
2186        for obj in Controls['SeqParFitEqList']:
2187            for var in obj.freeVars:
2188                if obj.freeVars[var][0] not in usedvarlist: usedvarlist.append(obj.freeVars[var][0])
2189
2190        dlg = G2exG.ExpressionDialog(
2191            G2frame.dataDisplay,indepVarDict,
2192            depVarDict=depVarDict,
2193            header='Define an equation to minimize in the parametric fit',
2194            ExtraButton=['Fit',SingleParEqFit],
2195            usedVars=usedvarlist)
2196        obj = dlg.Show(True)
2197        dlg.Destroy()
2198        if obj:
2199            Controls['SeqParFitEqList'].append(obj)
2200            EnableParFitEqMenus()
2201            if Controls['SeqParFitEqList']: DoParEqFit(event)
2202               
2203    def CopyParFitEq(event):
2204        'Copy an existing parametric equation to be fit to sequential results'
2205        # compile the variable names used in previous freevars to avoid accidental name collisions
2206        usedvarlist = []
2207        for obj in Controls['SeqParFitEqList']:
2208            for var in obj.freeVars:
2209                if obj.freeVars[var][0] not in usedvarlist: usedvarlist.append(obj.freeVars[var][0])
2210        txtlst = [obj.GetDepVar()+' = '+obj.expression for obj in Controls['SeqParFitEqList']]
2211        if len(txtlst) == 1:
2212            selected = 0
2213        else:
2214            selected = G2G.ItemSelector(
2215                txtlst,G2frame.dataFrame,
2216                multiple=False,
2217                title='Select a parametric equation to copy',
2218                header='Copy equation')
2219        if selected is not None:
2220            newEqn = copy.deepcopy(Controls['SeqParFitEqList'][selected])
2221            for var in newEqn.freeVars:
2222                newEqn.freeVars[var][0] = G2obj.MakeUniqueLabel(newEqn.freeVars[var][0],usedvarlist)
2223            dlg = G2exG.ExpressionDialog(
2224                G2frame.dataDisplay,indepVarDict,
2225                newEqn,
2226                depVarDict=depVarDict,
2227                header="Edit the formula for this minimization function",
2228                ExtraButton=['Fit',SingleParEqFit])
2229            newobj = dlg.Show(True)
2230            if newobj:
2231                calcobj = G2obj.ExpressionCalcObj(newobj)
2232                Controls['SeqParFitEqList'].append(newobj)
2233                EnableParFitEqMenus()
2234            if Controls['SeqParFitEqList']: DoParEqFit(event)
2235                                           
2236    def GridSetToolTip(row,col):
2237        '''Routine to show standard uncertainties for each element in table
2238        as a tooltip
2239        '''
2240        if colSigs[col]:
2241            return u'\u03c3 = '+str(colSigs[col][row])
2242        return ''
2243       
2244    def GridColLblToolTip(col):
2245        '''Define a tooltip for a column. This will be the user-entered value
2246        (from data['variableLabels']) or the default name
2247        '''
2248        if col < 0 or col > len(colLabels):
2249            print 'Illegal column #',col
2250            return
2251        var = colLabels[col]
2252        return variableLabels.get(var,G2obj.fmtVarDescr(var))
2253       
2254    def SetLabelString(event):
2255        '''Define or edit the label for a column in the table, to be used
2256        as a tooltip and for plotting
2257        '''
2258        col = event.GetCol()
2259        if col < 0 or col > len(colLabels):
2260            return
2261        var = colLabels[col]
2262        lbl = variableLabels.get(var,G2obj.fmtVarDescr(var))
2263        dlg = G2G.SingleStringDialog(G2frame.dataFrame,'Set variable label',
2264                                 'Set a new name for variable '+var,lbl,size=(400,-1))
2265        if dlg.Show():
2266            variableLabels[var] = dlg.GetValue()
2267        dlg.Destroy()
2268       
2269    #def GridRowLblToolTip(row): return 'Row ='+str(row)
2270   
2271    # lookup table for unique cell parameters by symmetry
2272    cellGUIlist = [
2273        [['m3','m3m'],(0,)],
2274        [['3R','3mR'],(0,3)],
2275        [['3','3m1','31m','6/m','6/mmm','4/m','4/mmm'],(0,2)],
2276        [['mmm'],(0,1,2)],
2277        [['2/m'+'a'],(0,1,2,3)],
2278        [['2/m'+'b'],(0,1,2,4)],
2279        [['2/m'+'c'],(0,1,2,5)],
2280        [['-1'],(0,1,2,3,4,5)],
2281        ]
2282    # cell labels
2283    cellUlbl = ('a','b','c',u'\u03B1',u'\u03B2',u'\u03B3') # unicode a,b,c,alpha,beta,gamma
2284
2285    #======================================================================
2286    # start processing sequential results here (UpdateSeqResults)
2287    #======================================================================
2288    if not data:
2289        print 'No sequential refinement results'
2290        return
2291    variableLabels = data.get('variableLabels',{})
2292    data['variableLabels'] = variableLabels
2293    Histograms,Phases = G2frame.GetUsedHistogramsAndPhasesfromTree()
2294    Controls = G2frame.PatternTree.GetItemPyData(GetPatternTreeItemId(G2frame,G2frame.root,'Controls'))
2295    # create a place to store Pseudo Vars & Parametric Fit functions, if not present
2296    if 'SeqPseudoVars' not in Controls: Controls['SeqPseudoVars'] = {}
2297    if 'SeqParFitEqList' not in Controls: Controls['SeqParFitEqList'] = []
2298    histNames = data['histNames']
2299    if G2frame.dataDisplay:
2300        G2frame.dataDisplay.Destroy()
2301    if not G2frame.dataFrame.GetStatusBar():
2302        Status = G2frame.dataFrame.CreateStatusBar()
2303        Status.SetStatusText("Select column to export; Double click on column to plot data; on row for Covariance")
2304    sampleParms = GetSampleParms()
2305
2306    # make dict of varied atom coords keyed by absolute position
2307    newAtomDict = data[histNames[0]].get('newAtomDict',{}) # dict with atom positions; relative & absolute
2308    # Possible error: the next might need to be data[histNames[0]]['varyList']
2309    # error will arise if there constraints on coordinates?
2310    atomLookup = {newAtomDict[item][0]:item for item in newAtomDict if item in data['varyList']}
2311   
2312    # make dict of varied cell parameters equivalents
2313    ESDlookup = {} # provides the Dij term for each Ak term (where terms are refined)
2314    Dlookup = {} # provides the Ak term for each Dij term (where terms are refined)
2315    # N.B. These Dij vars are missing a histogram #
2316    newCellDict = data[histNames[0]].get('newCellDict',{})
2317    for item in newCellDict:
2318        if item in data['varyList']:
2319            ESDlookup[newCellDict[item][0]] = item
2320            Dlookup[item] = newCellDict[item][0]
2321    # add coordinate equivalents to lookup table
2322    for parm in atomLookup:
2323        Dlookup[atomLookup[parm]] = parm
2324        ESDlookup[parm] = atomLookup[parm]
2325
2326    # get unit cell & symmetry for all phases & initial stuff for later use
2327    RecpCellTerms = {}
2328    SGdata = {}
2329    uniqCellIndx = {}
2330    initialCell = {}
2331    RcellLbls = {}
2332    zeroDict = {}
2333    Rcelldict = {}
2334    for phase in Phases:
2335        phasedict = Phases[phase]
2336        pId = phasedict['pId']
2337        pfx = str(pId)+'::' # prefix for A values from phase
2338        RcellLbls[pId] = [pfx+'A'+str(i) for i in range(6)]
2339        RecpCellTerms[pId] = G2lat.cell2A(phasedict['General']['Cell'][1:7])
2340        zeroDict[pId] = dict(zip(RcellLbls[pId],6*[0.,]))
2341        SGdata[pId] = phasedict['General']['SGData']
2342        Rcelldict.update({lbl:val for lbl,val in zip(RcellLbls[pId],RecpCellTerms[pId])})
2343        laue = SGdata[pId]['SGLaue']
2344        if laue == '2/m':
2345            laue += SGdata[pId]['SGUniq']
2346        for symlist,celllist in cellGUIlist:
2347            if laue in symlist:
2348                uniqCellIndx[pId] = celllist
2349                break
2350        else: # should not happen
2351            uniqCellIndx[pId] = range(6)
2352        for i in uniqCellIndx[pId]:
2353            initialCell[str(pId)+'::A'+str(i)] =  RecpCellTerms[pId][i]
2354
2355    SetDataMenuBar(G2frame,G2frame.dataFrame.SequentialMenu)
2356    G2frame.dataFrame.SetLabel('Sequential refinement results')
2357    if not G2frame.dataFrame.GetStatusBar():
2358        Status = G2frame.dataFrame.CreateStatusBar()
2359        Status.SetStatusText('')
2360    G2frame.dataFrame.Bind(wx.EVT_MENU, OnRenameSelSeq, id=wxID_RENAMESEQSEL)
2361    G2frame.dataFrame.Bind(wx.EVT_MENU, OnSaveSelSeq, id=wxID_SAVESEQSEL)
2362    G2frame.dataFrame.Bind(wx.EVT_MENU, OnSaveSelSeqCSV, id=wxID_SAVESEQSELCSV)
2363    G2frame.dataFrame.Bind(wx.EVT_MENU, OnSaveSeqCSV, id=wxID_SAVESEQCSV)
2364    G2frame.dataFrame.Bind(wx.EVT_MENU, OnPlotSelSeq, id=wxID_PLOTSEQSEL)
2365    G2frame.dataFrame.Bind(wx.EVT_MENU, OnAveSelSeq, id=wxID_AVESEQSEL)
2366    G2frame.dataFrame.Bind(wx.EVT_MENU, OnReOrgSelSeq, id=wxID_ORGSEQSEL)
2367    G2frame.dataFrame.Bind(wx.EVT_MENU, AddNewPseudoVar, id=wxADDSEQVAR)
2368    G2frame.dataFrame.Bind(wx.EVT_MENU, DelPseudoVar, id=wxDELSEQVAR)
2369    G2frame.dataFrame.Bind(wx.EVT_MENU, EditPseudoVar, id=wxEDITSEQVAR)
2370    G2frame.dataFrame.Bind(wx.EVT_MENU, AddNewParFitEq, id=wxADDPARFIT)
2371    G2frame.dataFrame.Bind(wx.EVT_MENU, CopyParFitEq, id=wxCOPYPARFIT)
2372    G2frame.dataFrame.Bind(wx.EVT_MENU, DelParFitEq, id=wxDELPARFIT)
2373    G2frame.dataFrame.Bind(wx.EVT_MENU, EditParFitEq, id=wxEDITPARFIT)
2374    G2frame.dataFrame.Bind(wx.EVT_MENU, DoParEqFit, id=wxDOPARFIT)
2375    EnablePseudoVarMenus()
2376    EnableParFitEqMenus()
2377
2378    # scan for locations where the variables change
2379    VaryListChanges = [] # histograms where there is a change
2380    combinedVaryList = []
2381    firstValueDict = {}
2382    vallookup = {}
2383    posdict = {}
2384    prevVaryList = []
2385    for i,name in enumerate(histNames):
2386        for var,val,sig in zip(data[name]['varyList'],data[name]['variables'],data[name]['sig']):
2387            svar = striphist(var,'*') # wild-carded
2388            if svar not in combinedVaryList:
2389                # add variables to list as they appear
2390                combinedVaryList.append(svar)
2391                firstValueDict[svar] = (val,sig)
2392        if prevVaryList != data[name]['varyList']: # this refinement has a different refinement list from previous
2393            prevVaryList = data[name]['varyList']
2394            vallookup[name] = dict(zip(data[name]['varyList'],data[name]['variables']))
2395            posdict[name] = {}
2396            for var in data[name]['varyList']:
2397                svar = striphist(var,'*')
2398                posdict[name][combinedVaryList.index(svar)] = svar
2399            VaryListChanges.append(name)
2400    if len(VaryListChanges) > 1:
2401        G2frame.dataFrame.SequentialFile.Enable(wxID_ORGSEQSEL,True)
2402    else:
2403        G2frame.dataFrame.SequentialFile.Enable(wxID_ORGSEQSEL,False)
2404    #-----------------------------------------------------------------------------------
2405    # build up the data table by columns -----------------------------------------------
2406    nRows = len(histNames)
2407    colList = [nRows*[True]]
2408    colSigs = [None]
2409    colLabels = ['Use']
2410    Types = [wg.GRID_VALUE_BOOL]
2411    # start with Rwp values
2412    if 'IMG ' not in histNames[0][:4]:
2413        colList += [[data[name]['Rvals']['Rwp'] for name in histNames]]
2414        colSigs += [None]
2415        colLabels += ['Rwp']
2416        Types += [wg.GRID_VALUE_FLOAT+':10,3',]
2417    # add % change in Chi^2 in last cycle
2418    if histNames[0][:4] not in ['SASD','IMG '] and Controls.get('ShowCell'):
2419        colList += [[100.*data[name]['Rvals'].get('DelChi2',-1) for name in histNames]]
2420        colSigs += [None]
2421        colLabels += [u'\u0394\u03C7\u00B2 (%)']
2422        Types += [wg.GRID_VALUE_FLOAT,]
2423    deltaChiCol = len(colLabels)-1
2424    # add changing sample parameters to table
2425    for key in sampleParms:
2426        colList += [sampleParms[key]]
2427        colSigs += [None]
2428        colLabels += [key]
2429        Types += [wg.GRID_VALUE_FLOAT,]
2430    sampleDict = {}
2431    for i,name in enumerate(histNames):
2432        sampleDict[name] = dict(zip(sampleParms.keys(),[sampleParms[key][i] for key in sampleParms.keys()])) 
2433    # add unique cell parameters TODO: review this where the cell symmetry changes (when possible)
2434    if Controls.get('ShowCell',False):
2435        for pId in sorted(RecpCellTerms):
2436            pfx = str(pId)+'::' # prefix for A values from phase
2437            cells = []
2438            cellESDs = []
2439            colLabels += [pfx+cellUlbl[i] for i in uniqCellIndx[pId]]
2440            colLabels += [pfx+'Vol']
2441            Types += (1+len(uniqCellIndx[pId]))*[wg.GRID_VALUE_FLOAT,]
2442            for name in histNames:
2443                covData = {
2444                    'varyList': [Dlookup.get(striphist(v),v) for v in data[name]['varyList']],
2445                    'covMatrix': data[name]['covMatrix']
2446                    }
2447                A = RecpCellTerms[pId][:] # make copy of starting A values
2448                # update with refined values
2449                for i in range(6):
2450                    var = str(pId)+'::A'+str(i)
2451                    if var in ESDlookup:
2452                        val = data[name]['newCellDict'][ESDlookup[var]][1] # get refined value
2453                        A[i] = val # override with updated value
2454                # apply symmetry
2455                Albls = [pfx+'A'+str(i) for i in range(6)]
2456                cellDict = dict(zip(Albls,A))
2457                A,zeros = G2stIO.cellFill(pfx,SGdata[pId],cellDict,zeroDict[pId])
2458                # convert to direct cell & add only unique values to table
2459                c = G2lat.A2cell(A)
2460                vol = G2lat.calc_V(A)
2461                cE = G2stIO.getCellEsd(pfx,SGdata[pId],A,covData)
2462                cells += [[c[i] for i in uniqCellIndx[pId]]+[vol]]
2463                cellESDs += [[cE[i] for i in uniqCellIndx[pId]]+[cE[-1]]]
2464            colList += zip(*cells)
2465            colSigs += zip(*cellESDs)
2466    # sort out the variables in their selected order
2467    varcols = 0
2468    for d in posdict.itervalues():
2469        varcols = max(varcols,max(d.keys())+1)
2470    # get labels for each column
2471    for i in range(varcols):
2472        lbl = ''
2473        for h in VaryListChanges:
2474            if posdict[h].get(i):
2475                if posdict[h].get(i) in lbl: continue
2476                if lbl != "": lbl += '/'
2477                lbl += posdict[h].get(i)
2478        colLabels.append(lbl)
2479    Types += varcols*[wg.GRID_VALUE_FLOAT]
2480    vals = []
2481    esds = []
2482    varsellist = None        # will be a list of variable names in the order they are selected to appear
2483    # tabulate values for each hist, leaving None for blank columns
2484    for name in histNames:
2485        if name in posdict:
2486            varsellist = [posdict[name].get(i) for i in range(varcols)]
2487            # translate variable names to how they will be used in the headings
2488            vs = [striphist(v,'*') for v in data[name]['varyList']]
2489            # determine the index for each column (or None) in the data[]['variables'] and ['sig'] lists
2490            sellist = [vs.index(v) if v is not None else None for v in varsellist]
2491            #sellist = [i if striphist(v,'*') in varsellist else None for i,v in enumerate(data[name]['varyList'])]
2492        if not varsellist: raise Exception()
2493        vals.append([data[name]['variables'][s] if s is not None else None for s in sellist])
2494        esds.append([data[name]['sig'][s] if s is not None else None for s in sellist])
2495        #GSASIIpath.IPyBreak()
2496    colList += zip(*vals)
2497    colSigs += zip(*esds)
2498               
2499    # tabulate constrained variables, removing histogram numbers if needed
2500    # from parameter label
2501    depValDict = {}
2502    depSigDict = {}
2503    for name in histNames:
2504        for var in data[name].get('depParmDict',{}):
2505            val,sig = data[name]['depParmDict'][var]
2506            svar = striphist(var,'*')
2507            if svar not in depValDict:
2508               depValDict[svar] = [val]
2509               depSigDict[svar] = [sig]
2510            else:
2511               depValDict[svar].append(val)
2512               depSigDict[svar].append(sig)
2513    # add the dependent constrained variables to the table
2514    for var in sorted(depValDict):
2515        if len(depValDict[var]) != len(histNames): continue
2516        colLabels.append(var)
2517        Types += [wg.GRID_VALUE_FLOAT,]
2518        colSigs += [depSigDict[var]]
2519        colList += [depValDict[var]]
2520
2521    # add atom parameters to table
2522    colLabels += atomLookup.keys()
2523    Types += len(atomLookup)*[wg.GRID_VALUE_FLOAT]
2524    for parm in sorted(atomLookup):
2525        colList += [[data[name]['newAtomDict'][atomLookup[parm]][1] for name in histNames]]
2526        if atomLookup[parm] in data[histNames[0]]['varyList']:
2527            col = data[histNames[0]]['varyList'].index(atomLookup[parm])
2528            colSigs += [[data[name]['sig'][col] for name in histNames]]
2529        else:
2530            colSigs += [None] # should not happen
2531    # evaluate Pseudovars, their ESDs and add them to grid
2532    for expr in Controls['SeqPseudoVars']:
2533        obj = Controls['SeqPseudoVars'][expr]
2534        calcobj = G2obj.ExpressionCalcObj(obj)
2535        valList = []
2536        esdList = []
2537        for seqnum,name in enumerate(histNames):
2538            sigs = data[name]['sig']
2539            G2mv.InitVars()
2540            parmDict = data[name].get('parmDict')
2541            badVary = data[name].get('badVary',[])
2542            constraintInfo = data[name].get('constraintInfo',[[],[],{},[],seqnum])
2543            groups,parmlist,constrDict,fixedList,ihst = constraintInfo
2544            varyList = data[name]['varyList']
2545            parmDict = data[name]['parmDict']
2546            G2mv.GenerateConstraints(groups,parmlist,varyList,constrDict,fixedList,parmDict,SeqHist=ihst)
2547            derivs = np.array(
2548                [EvalPSvarDeriv(calcobj,parmDict.copy(),sampleDict[name],var,ESD)
2549                 for var,ESD in zip(varyList,sigs)]
2550                )
2551            esdList.append(np.sqrt(
2552                np.inner(derivs,np.inner(data[name]['covMatrix'],derivs.T))
2553                ))
2554            PSvarDict = parmDict.copy()
2555            PSvarDict.update(sampleDict[name])
2556            UpdateParmDict(PSvarDict)
2557            calcobj.UpdateDict(PSvarDict)
2558            valList.append(calcobj.EvalExpression())
2559        if not esdList:
2560            esdList = None
2561        colList += [valList]
2562        colSigs += [esdList]
2563        colLabels += [expr]
2564        Types += [wg.GRID_VALUE_FLOAT,]
2565    #---- table build done -------------------------------------------------------------
2566
2567    # Make dict needed for creating & editing pseudovars (PSvarDict).
2568    name = histNames[0]
2569    parmDict = data[name].get('parmDict')
2570    PSvarDict = parmDict.copy()
2571    PSvarDict.update(sampleParms)
2572    UpdateParmDict(PSvarDict)
2573    # Also dicts of dependent (depVarDict) & independent vars (indepVarDict)
2574    # for Parametric fitting from the data table
2575    parmDict = dict(zip(colLabels,zip(*colList)[0])) # scratch dict w/all values in table
2576    parmDict.update(
2577        {var:val for var,val in data[name].get('newCellDict',{}).values()} #  add varied reciprocal cell terms
2578    )
2579    name = histNames[0]
2580
2581    #******************************************************************************
2582    # create a set of values for example evaluation of pseudovars and
2583    # this does not work for refinements that have differing numbers of variables.
2584    #raise Exception
2585    indepVarDict = {}     #  values in table w/o ESDs
2586    depVarDict = {}
2587    for i,var in enumerate(colLabels):
2588        if var == 'Use': continue
2589        if colList[i][0] is None:
2590            val,sig = firstValueDict.get(var,[None,None])
2591        elif colSigs[i]:
2592            val,sig = colList[i][0],colSigs[i][0]
2593        else:
2594            val,sig = colList[i][0],None
2595        if val is None:
2596            continue
2597        elif sig is None:
2598            indepVarDict[var] = val
2599        elif striphist(var) not in Dlookup:
2600            depVarDict[var] = val
2601    # add recip cell coeff. values
2602    depVarDict.update({var:val for var,val in data[name].get('newCellDict',{}).values()})
2603
2604    G2frame.dataDisplay = G2G.GSGrid(parent=G2frame.dataFrame)
2605    G2frame.SeqTable = G2G.Table(
2606        [list(c) for c in zip(*colList)],     # convert from columns to rows
2607        colLabels=colLabels,rowLabels=histNames,types=Types)
2608    G2frame.dataDisplay.SetTable(G2frame.SeqTable, True)
2609    #G2frame.dataDisplay.EnableEditing(False)
2610    # make all but first column read-only
2611    for c in range(1,len(colLabels)):
2612        for r in range(nRows):
2613            G2frame.dataDisplay.SetCellReadOnly(r,c)
2614    G2frame.dataDisplay.Bind(wg.EVT_GRID_LABEL_LEFT_DCLICK, PlotSelect)
2615    G2frame.dataDisplay.Bind(wg.EVT_GRID_LABEL_RIGHT_CLICK, SetLabelString)
2616    G2frame.dataDisplay.SetRowLabelSize(8*len(histNames[0]))       #pretty arbitrary 8
2617    G2frame.dataDisplay.SetMargins(0,0)
2618    G2frame.dataDisplay.AutoSizeColumns(True)
2619    if prevSize:
2620        G2frame.dataDisplay.SetSize(prevSize)
2621    else:
2622        G2frame.dataFrame.setSizePosLeft([700,350])
2623    # highlight unconverged shifts
2624    if histNames[0][:4] not in ['SASD','IMG ']:
2625        for row,name in enumerate(histNames):
2626            deltaChi = G2frame.SeqTable.GetValue(row,deltaChiCol)
2627            if deltaChi > 10.:
2628                G2frame.dataDisplay.SetCellStyle(row,deltaChiCol,color=wx.Colour(255,0,0))
2629            elif deltaChi > 1.0:
2630                G2frame.dataDisplay.SetCellStyle(row,deltaChiCol,color=wx.Colour(255,255,0))
2631    G2frame.dataDisplay.InstallGridToolTip(GridSetToolTip,GridColLblToolTip)
2632    G2frame.dataDisplay.SendSizeEvent() # resize needed on mac
2633    G2frame.dataDisplay.Refresh() # shows colored text on mac
2634   
2635################################################################################
2636#####  Main PWDR panel
2637################################################################################           
2638       
2639def UpdatePWHKPlot(G2frame,kind,item):
2640    '''Called when the histogram main tree entry is called. Displays the
2641    histogram weight factor, refinement statistics for the histogram
2642    and the range of data for a simulation.
2643
2644    Also invokes a plot of the histogram.
2645    '''
2646    def onEditSimRange(event):
2647        'Edit simulation range'
2648        inp = [
2649            min(data[1][0]),
2650            max(data[1][0]),
2651            None
2652            ]
2653        inp[2] = (inp[1] - inp[0])/(len(data[1][0])-1.)
2654        names = ('start angle', 'end angle', 'step size')
2655        dictlst = [inp] * len(inp)
2656        elemlst = range(len(inp))
2657        dlg = G2G.ScrolledMultiEditor(
2658            G2frame,[inp] * len(inp), range(len(inp)), names,
2659            header='Edit simulation range',
2660            minvals=(0.001,0.001,0.0001),
2661            maxvals=(180.,180.,.1),
2662            )
2663        dlg.CenterOnParent()
2664        val = dlg.ShowModal()
2665        dlg.Destroy()
2666        if val != wx.ID_OK: return
2667        if inp[0] > inp[1]:
2668            end,start,step = inp
2669        else:               
2670            start,end,step = inp
2671        step = abs(step)
2672        N = int((end-start)/step)+1
2673        newdata = np.linspace(start,end,N,True)
2674        if len(newdata) < 2: return # too small a range - reject
2675        data[1] = [newdata,np.zeros_like(newdata),np.ones_like(newdata),
2676            np.zeros_like(newdata),np.zeros_like(newdata),np.zeros_like(newdata)]
2677        Tmin = newdata[0]
2678        Tmax = newdata[-1]
2679        G2frame.PatternTree.SetItemPyData(GetPatternTreeItemId(G2frame,item,'Limits'),
2680            [(Tmin,Tmax),[Tmin,Tmax]])
2681        UpdatePWHKPlot(G2frame,kind,item) # redisplay data screen
2682
2683    def OnPlot3DHKL(event):
2684        refList = data[1]['RefList']
2685        FoMax = np.max(refList.T[8+Super])
2686        Hmin = np.array([int(np.min(refList.T[0])),int(np.min(refList.T[1])),int(np.min(refList.T[2]))])
2687        Hmax = np.array([int(np.max(refList.T[0])),int(np.max(refList.T[1])),int(np.max(refList.T[2]))])
2688        Vpoint = [int(np.mean(refList.T[0])),int(np.mean(refList.T[1])),int(np.mean(refList.T[2]))]
2689        controls = {'Type' : 'Fosq','Iscale' : False,'HKLmax' : Hmax,'HKLmin' : Hmin,
2690            'FoMax' : FoMax,'Scale' : 1.0,'Drawing':{'viewPoint':[Vpoint,[]],'default':Vpoint[:],
2691            'backColor':[0,0,0],'depthFog':False,'Zclip':10.0,'cameraPos':10.,'Zstep':0.05,
2692            'Scale':1.0,'oldxy':[],'viewDir':[1,0,0]},'Super':Super,'SuperVec':SuperVec}
2693        G2plt.Plot3DSngl(G2frame,newPlot=True,Data=controls,hklRef=refList,Title=phaseName)
2694       
2695    def OnPlotAll3DHKL(event):
2696        choices = GetPatternTreeDataNames(G2frame,['HKLF',])
2697        dlg = G2G.G2MultiChoiceDialog(G2frame, 'Select reflection sets to plot',
2698            'Use data',choices)
2699        try:
2700            if dlg.ShowModal() == wx.ID_OK:
2701                refNames = [choices[i] for i in dlg.GetSelections()]
2702            else:
2703                return
2704        finally:
2705            dlg.Destroy()
2706        refList = np.zeros(0)
2707        for name in refNames:
2708            Id = GetPatternTreeItemId(G2frame,G2frame.root, name)
2709            reflData = G2frame.PatternTree.GetItemPyData(Id)[1]
2710            if len(refList):
2711                refList = np.concatenate((refList,reflData['RefList']))
2712            else:
2713                refList = reflData['RefList']
2714           
2715        FoMax = np.max(refList.T[8+Super])
2716        Hmin = np.array([int(np.min(refList.T[0])),int(np.min(refList.T[1])),int(np.min(refList.T[2]))])
2717        Hmax = np.array([int(np.max(refList.T[0])),int(np.max(refList.T[1])),int(np.max(refList.T[2]))])
2718        Vpoint = [int(np.mean(refList.T[0])),int(np.mean(refList.T[1])),int(np.mean(refList.T[2]))]
2719        controls = {'Type' : 'Fosq','Iscale' : False,'HKLmax' : Hmax,'HKLmin' : Hmin,
2720            'FoMax' : FoMax,'Scale' : 1.0,'Drawing':{'viewPoint':[Vpoint,[]],'default':Vpoint[:],
2721            'backColor':[0,0,0],'depthFog':False,'Zclip':10.0,'cameraPos':10.,'Zstep':0.05,
2722            'Scale':1.0,'oldxy':[],'viewDir':[1,0,0]},'Super':Super,'SuperVec':SuperVec}
2723        G2plt.Plot3DSngl(G2frame,newPlot=True,Data=controls,hklRef=refList,Title=phaseName)
2724       
2725       
2726    def OnErrorAnalysis(event):
2727        G2plt.PlotDeltSig(G2frame,kind)
2728       
2729    def OnWtFactor(event):
2730        try:
2731            val = float(wtval.GetValue())
2732        except ValueError:
2733            val = data[0]['wtFactor']
2734        data[0]['wtFactor'] = val
2735        wtval.SetValue('%.3f'%(val))
2736       
2737    def onCopyPlotCtrls(event):
2738        '''Respond to menu item to copy multiple sections from a histogram.
2739        Need this here to pass on the G2frame object.
2740        '''
2741        G2pdG.CopyPlotCtrls(G2frame)
2742
2743    def onCopySelectedItems(event):
2744        '''Respond to menu item to copy multiple sections from a histogram.
2745        Need this here to pass on the G2frame object.
2746        '''
2747        G2pdG.CopySelectedHistItems(G2frame)
2748           
2749    data = G2frame.PatternTree.GetItemPyData(item)
2750#patches
2751    if 'wtFactor' not in data[0]:
2752        data[0] = {'wtFactor':1.0}
2753    #if isinstance(data[1],list) and kind == 'HKLF':
2754    if 'list' in str(type(data[1])) and kind == 'HKLF':
2755        RefData = {'RefList':[],'FF':[]}
2756        for ref in data[1]:
2757            RefData['RefList'].append(ref[:11]+[ref[13],])
2758            RefData['FF'].append(ref[14])
2759        data[1] = RefData
2760        G2frame.PatternTree.SetItemPyData(item,data)
2761#end patches
2762    if G2frame.dataDisplay:
2763        G2frame.dataDisplay.Destroy()
2764    if kind in ['PWDR','SASD']:
2765        SetDataMenuBar(G2frame,G2frame.dataFrame.PWDRMenu)
2766        G2frame.dataFrame.Bind(wx.EVT_MENU, OnErrorAnalysis, id=wxID_PWDANALYSIS)
2767        G2frame.dataFrame.Bind(wx.EVT_MENU, onCopySelectedItems, id=wxID_PWDCOPY)
2768        G2frame.dataFrame.Bind(wx.EVT_MENU, onCopyPlotCtrls, id=wxID_PLOTCTRLCOPY)
2769    elif kind in ['HKLF',]:
2770        SetDataMenuBar(G2frame,G2frame.dataFrame.HKLFMenu)
2771        G2frame.dataFrame.Bind(wx.EVT_MENU, OnErrorAnalysis, id=wxID_PWDANALYSIS)
2772        G2frame.dataFrame.Bind(wx.EVT_MENU, OnPlot3DHKL, id=wxID_PWD3DHKLPLOT)
2773        G2frame.dataFrame.Bind(wx.EVT_MENU, OnPlotAll3DHKL, id=wxID_3DALLHKLPLOT)
2774#        G2frame.dataFrame.Bind(wx.EVT_MENU, onCopySelectedItems, id=wxID_PWDCOPY)
2775    G2frame.dataDisplay = wx.Panel(G2frame.dataFrame)
2776   
2777    mainSizer = wx.BoxSizer(wx.VERTICAL)
2778    mainSizer.Add((5,5),)
2779    wtSizer = wx.BoxSizer(wx.HORIZONTAL)
2780    wtSizer.Add(wx.StaticText(G2frame.dataDisplay,-1,' Weight factor: '),0,WACV)
2781    wtval = wx.TextCtrl(G2frame.dataDisplay,-1,'%.3f'%(data[0]['wtFactor']),style=wx.TE_PROCESS_ENTER)
2782    wtval.Bind(wx.EVT_TEXT_ENTER,OnWtFactor)
2783    wtval.Bind(wx.EVT_KILL_FOCUS,OnWtFactor)
2784    wtSizer.Add(wtval,0,WACV)
2785    mainSizer.Add(wtSizer)
2786    if data[0].get('Dummy'):
2787        simSizer = wx.BoxSizer(wx.HORIZONTAL)
2788        Tmin = min(data[1][0])
2789        Tmax = max(data[1][0])
2790        num = len(data[1][0])
2791        step = (Tmax - Tmin)/(num-1)
2792        t = u'2\u03b8' # 2theta
2793        lbl =  u'Simulation range: {:.2f} to {:.2f} {:s}\nwith {:.4f} steps ({:d} points)'
2794        lbl += u'\n(Edit range resets observed intensities).'
2795        lbl = lbl.format(Tmin,Tmax,t,step,num)
2796        simSizer.Add(wx.StaticText(G2frame.dataDisplay,wx.ID_ANY,lbl),
2797                    0,WACV)
2798        but = wx.Button(G2frame.dataDisplay,wx.ID_ANY,"Edit range")
2799        but.Bind(wx.EVT_BUTTON,onEditSimRange)
2800        simSizer.Add(but,0,WACV)
2801        mainSizer.Add(simSizer)
2802    if 'Nobs' in data[0]:
2803        mainSizer.Add(wx.StaticText(G2frame.dataDisplay,-1,
2804            ' Data residual wR: %.3f%% on %d observations'%(data[0]['wR'],data[0]['Nobs'])))
2805        for value in data[0]:
2806            if 'Nref' in value:
2807                mainSizer.Add((5,5),)
2808                pfx = value.split('Nref')[0]
2809                name = data[0].get(pfx.split(':')[0]+'::Name','?')
2810                mainSizer.Add(wx.StaticText(G2frame.dataDisplay,-1,' For phase '+name+':'))
2811                mainSizer.Add(wx.StaticText(G2frame.dataDisplay,-1,
2812                    u' Unweighted phase residuals RF\u00b2: %.3f%%, RF: %.3f%% on %d reflections  '% \
2813                    (data[0][pfx+'Rf^2'],data[0][pfx+'Rf'],data[0][value])))
2814    mainSizer.Add((5,5),)
2815    mainSizer.Layout()   
2816    G2frame.dataDisplay.SetSizer(mainSizer)
2817    Size = mainSizer.Fit(G2frame.dataFrame)
2818    Size[1] += 10
2819    G2frame.dataFrame.setSizePosLeft(Size)
2820    G2frame.PatternTree.SetItemPyData(item,data)
2821    if kind in ['PWDR','SASD']:
2822        G2plt.PlotPatterns(G2frame,plotType=kind,newPlot=True)
2823    elif kind == 'HKLF':
2824        Name = G2frame.PatternTree.GetItemText(item)
2825        phaseName = G2pdG.IsHistogramInAnyPhase(G2frame,Name)
2826        if phaseName:
2827            pId = GetPatternTreeItemId(G2frame,G2frame.root,'Phases')
2828            phaseId =  GetPatternTreeItemId(G2frame,pId,phaseName)
2829            General = G2frame.PatternTree.GetItemPyData(phaseId)['General']
2830            Super = General.get('Super',0)
2831            SuperVec = General.get('SuperVec',[])
2832        else:
2833            Super = 0
2834            SuperVec = []       
2835        refList = data[1]['RefList']
2836        FoMax = np.max(refList.T[5+data[1].get('Super',0)])
2837        page = G2frame.G2plotNB.nb.GetSelection()
2838        tab = ''
2839        if page >= 0:
2840            tab = G2frame.G2plotNB.nb.GetPageText(page)
2841        if '3D' in tab:
2842            Hmin = np.array([int(np.min(refList.T[0])),int(np.min(refList.T[1])),int(np.min(refList.T[2]))])
2843            Hmax = np.array([int(np.max(refList.T[0])),int(np.max(refList.T[1])),int(np.max(refList.T[2]))])
2844            Vpoint = [int(np.mean(refList.T[0])),int(np.mean(refList.T[1])),int(np.mean(refList.T[2]))]
2845            Page = G2frame.G2plotNB.nb.GetPage(page)
2846            controls = Page.controls
2847            G2plt.Plot3DSngl(G2frame,newPlot=False,Data=controls,hklRef=refList,Title=phaseName)
2848        else:
2849            controls = {'Type' : 'Fo','ifFc' : True,     
2850                'HKLmax' : [int(np.max(refList.T[0])),int(np.max(refList.T[1])),int(np.max(refList.T[2]))],
2851                'HKLmin' : [int(np.min(refList.T[0])),int(np.min(refList.T[1])),int(np.min(refList.T[2]))],
2852                'FoMax' : FoMax,'Zone' : '001','Layer' : 0,'Scale' : 1.0,'Super':Super,'SuperVec':SuperVec}
2853            G2plt.PlotSngl(G2frame,newPlot=True,Data=controls,hklRef=refList)
2854                 
2855################################################################################
2856#####  Pattern tree routines
2857################################################################################           
2858       
2859def GetPatternTreeDataNames(G2frame,dataTypes):
2860    '''Needs a doc string
2861    '''
2862    names = []
2863    item, cookie = G2frame.PatternTree.GetFirstChild(G2frame.root)       
2864    while item:
2865        name = G2frame.PatternTree.GetItemText(item)
2866        if name[:4] in dataTypes:
2867            names.append(name)
2868        item, cookie = G2frame.PatternTree.GetNextChild(G2frame.root, cookie)
2869    return names
2870                         
2871def GetPatternTreeItemId(G2frame, parentId, itemText):
2872    '''Needs a doc string
2873    '''
2874    item, cookie = G2frame.PatternTree.GetFirstChild(parentId)
2875    while item:
2876        if G2frame.PatternTree.GetItemText(item) == itemText:
2877            return item
2878        item, cookie = G2frame.PatternTree.GetNextChild(parentId, cookie)
2879    return 0               
2880
2881def MovePatternTreeToGrid(G2frame,item):
2882    '''Called from GSASII.OnPatternTreeSelChanged when a item is selected on the tree
2883    '''
2884    pickName = G2frame.PatternTree.GetItemText(item)
2885    if G2frame.PickIdText == pickName:
2886        return
2887   
2888    oldPage = None # will be set later if already on a Phase item
2889    if G2frame.dataFrame:
2890        SetDataMenuBar(G2frame)
2891        if G2frame.dataFrame.GetLabel() == 'Comments':
2892            try:
2893                data = [G2frame.dataDisplay.GetValue()]
2894                G2frame.dataDisplay.Clear() 
2895                Id = GetPatternTreeItemId(G2frame,G2frame.root, 'Comments')
2896                if Id: G2frame.PatternTree.SetItemPyData(Id,data)
2897            except:     #clumsy but avoids dead window problem when opening another project
2898                pass
2899        elif G2frame.dataFrame.GetLabel() == 'Notebook':
2900            try:
2901                data = [G2frame.dataDisplay.GetValue()]
2902                G2frame.dataDisplay.Clear() 
2903                Id = GetPatternTreeItemId(G2frame,G2frame.root, 'Notebook')
2904                if Id: G2frame.PatternTree.SetItemPyData(Id,data)
2905            except:     #clumsy but avoids dead window problem when opening another project
2906                pass
2907        elif 'Phase Data for' in G2frame.dataFrame.GetLabel():
2908            if G2frame.dataDisplay: 
2909                oldPage = G2frame.dataDisplay.GetSelection()
2910        G2frame.dataFrame.Clear()
2911        G2frame.dataFrame.SetLabel('')
2912    else:
2913        #create the frame for the data item window
2914        G2frame.dataFrame = DataFrame(parent=G2frame.mainPanel,frame=G2frame)
2915        G2frame.dataFrame.PhaseUserSize = None
2916       
2917    G2frame.dataFrame.Raise()           
2918    G2frame.PickId = item
2919    G2frame.PickIdText = None
2920    parentID = G2frame.root
2921    #for i in G2frame.ExportPattern: i.Enable(False)
2922    defWid = [250,150]
2923    if item != G2frame.root:
2924        parentID = G2frame.PatternTree.GetItemParent(item)
2925    if G2frame.PatternTree.GetItemParent(item) == G2frame.root:
2926        G2frame.PatternId = item
2927        if G2frame.PatternTree.GetItemText(item) == 'Notebook':
2928            SetDataMenuBar(G2frame,G2frame.dataFrame.DataNotebookMenu)
2929            G2frame.PatternId = 0
2930            #for i in G2frame.ExportPattern: i.Enable(False)
2931            data = G2frame.PatternTree.GetItemPyData(item)
2932            UpdateNotebook(G2frame,data)
2933        elif G2frame.PatternTree.GetItemText(item) == 'Controls':
2934            G2frame.PatternId = 0
2935            #for i in G2frame.ExportPattern: i.Enable(False)
2936            data = G2frame.PatternTree.GetItemPyData(item)
2937            if not data:           #fill in defaults
2938                data = copy.copy(G2obj.DefaultControls)    #least squares controls
2939                G2frame.PatternTree.SetItemPyData(item,data)                             
2940            for i in G2frame.Refine: i.Enable(True)
2941            G2frame.EnableSeqRefineMenu()
2942            UpdateControls(G2frame,data)
2943        elif G2frame.PatternTree.GetItemText(item) == 'Sequential results':
2944            data = G2frame.PatternTree.GetItemPyData(item)
2945            UpdateSeqResults(G2frame,data)
2946        elif G2frame.PatternTree.GetItemText(item) == 'Covariance':
2947            data = G2frame.PatternTree.GetItemPyData(item)
2948            G2frame.dataFrame.setSizePosLeft(defWid)
2949            text = ''
2950            if 'Rvals' in data:
2951                Nvars = len(data['varyList'])
2952                Rvals = data['Rvals']
2953                text = '\nFinal residuals: \nwR = %.3f%% \nchi**2 = %.1f \nGOF = %.2f'%(Rvals['Rwp'],Rvals['chisq'],Rvals['GOF'])
2954                text += '\nNobs = %d \nNvals = %d'%(Rvals['Nobs'],Nvars)
2955                if 'lamMax' in Rvals:
2956                    text += '\nlog10 MaxLambda = %.1f'%(np.log10(Rvals['lamMax']))
2957            wx.TextCtrl(parent=G2frame.dataFrame,size=G2frame.dataFrame.GetClientSize(),
2958                value='See plot window for covariance display'+text,style=wx.TE_MULTILINE)
2959            G2plt.PlotCovariance(G2frame,data)
2960        elif G2frame.PatternTree.GetItemText(item) == 'Constraints':
2961            data = G2frame.PatternTree.GetItemPyData(item)
2962            G2cnstG.UpdateConstraints(G2frame,data)
2963        elif G2frame.PatternTree.GetItemText(item) == 'Rigid bodies':
2964            data = G2frame.PatternTree.GetItemPyData(item)
2965            G2cnstG.UpdateRigidBodies(G2frame,data)
2966        elif G2frame.PatternTree.GetItemText(item) == 'Restraints':
2967            data = G2frame.PatternTree.GetItemPyData(item)
2968            Phases = G2frame.GetPhaseData()
2969            phase = ''
2970            phaseName = ''
2971            if Phases:
2972                phaseName = Phases.keys()[0]
2973            G2frame.dataFrame.setSizePosLeft(defWid)
2974            G2restG.UpdateRestraints(G2frame,data,Phases,phaseName)
2975        elif 'IMG' in G2frame.PatternTree.GetItemText(item):
2976            G2frame.Image = item
2977            G2frame.dataFrame.SetTitle('Image Data')
2978            data = G2frame.PatternTree.GetItemPyData(GetPatternTreeItemId( \
2979                G2frame,item,'Image Controls'))
2980            G2imG.UpdateImageData(G2frame,data)
2981            G2plt.PlotImage(G2frame,newPlot=True)
2982        elif 'PKS' in G2frame.PatternTree.GetItemText(item):
2983            G2plt.PlotPowderLines(G2frame)
2984        elif 'PWDR' in G2frame.PatternTree.GetItemText(item):
2985            #for i in G2frame.ExportPattern: i.Enable(True)
2986            if G2frame.EnablePlot:
2987                UpdatePWHKPlot(G2frame,'PWDR',item)
2988        elif 'SASD' in G2frame.PatternTree.GetItemText(item):
2989            #for i in G2frame.ExportPattern: i.Enable(True)
2990            if G2frame.EnablePlot:
2991                UpdatePWHKPlot(G2frame,'SASD',item)
2992        elif 'HKLF' in G2frame.PatternTree.GetItemText(item):
2993            G2frame.Sngl = True
2994            UpdatePWHKPlot(G2frame,'HKLF',item)
2995        elif 'PDF' in G2frame.PatternTree.GetItemText(item):
2996            G2frame.PatternId = item
2997            for i in G2frame.ExportPDF: i.Enable(True)
2998            G2plt.PlotISFG(G2frame,type='S(Q)')
2999        elif G2frame.PatternTree.GetItemText(item) == 'Phases':
3000            G2frame.dataFrame.setSizePosLeft(defWid)
3001            wx.TextCtrl(parent=G2frame.dataFrame,size=G2frame.dataFrame.GetClientSize(),
3002                value='Select one phase to see its parameters')           
3003    elif 'I(Q)' in G2frame.PatternTree.GetItemText(item):
3004        G2frame.PatternId = G2frame.PatternTree.GetItemParent(item)
3005        data = G2frame.PatternTree.GetItemPyData(GetPatternTreeItemId(G2frame,G2frame.PatternId,'PDF Controls'))
3006        G2pdG.UpdatePDFGrid(G2frame,data)
3007        G2plt.PlotISFG(G2frame,type='I(Q)',newPlot=True)
3008    elif 'S(Q)' in G2frame.PatternTree.GetItemText(item):
3009        G2frame.PatternId = G2frame.PatternTree.GetItemParent(item)
3010        data = G2frame.PatternTree.GetItemPyData(GetPatternTreeItemId(G2frame,G2frame.PatternId,'PDF Controls'))
3011        G2pdG.UpdatePDFGrid(G2frame,data)
3012        G2plt.PlotISFG(G2frame,type='S(Q)',newPlot=True)
3013    elif 'F(Q)' in G2frame.PatternTree.GetItemText(item):
3014        G2frame.PatternId = G2frame.PatternTree.GetItemParent(item)
3015        data = G2frame.PatternTree.GetItemPyData(GetPatternTreeItemId(G2frame,G2frame.PatternId,'PDF Controls'))
3016        G2pdG.UpdatePDFGrid(G2frame,data)
3017        G2plt.PlotISFG(G2frame,type='F(Q)',newPlot=True)
3018    elif 'G(R)' in G2frame.PatternTree.GetItemText(item):
3019        G2frame.PatternId = G2frame.PatternTree.GetItemParent(item)
3020        data = G2frame.PatternTree.GetItemPyData(GetPatternTreeItemId(G2frame,G2frame.PatternId,'PDF Controls'))
3021        G2pdG.UpdatePDFGrid(G2frame,data)
3022        G2plt.PlotISFG(G2frame,type='G(R)',newPlot=True)           
3023    elif G2frame.PatternTree.GetItemText(parentID) == 'Phases':
3024        data = G2frame.PatternTree.GetItemPyData(item)
3025        G2phG.UpdatePhaseData(G2frame,item,data,oldPage)
3026    elif G2frame.PatternTree.GetItemText(item) == 'Comments':
3027        SetDataMenuBar(G2frame,G2frame.dataFrame.DataCommentsMenu)
3028        G2frame.PatternId = G2frame.PatternTree.GetItemParent(item)
3029        data = G2frame.PatternTree.GetItemPyData(item)
3030        UpdateComments(G2frame,data)
3031    elif G2frame.PatternTree.GetItemText(item) == 'Image Controls':
3032        G2frame.dataFrame.SetTitle('Image Controls')
3033        G2frame.Image = G2frame.PatternTree.GetItemParent(item)
3034        masks = G2frame.PatternTree.GetItemPyData(
3035            GetPatternTreeItemId(G2frame,G2frame.Image, 'Masks'))
3036        data = G2frame.PatternTree.GetItemPyData(item)
3037        G2imG.UpdateImageControls(G2frame,data,masks)
3038        G2plt.PlotImage(G2frame)
3039    elif G2frame.PatternTree.GetItemText(item) == 'Masks':
3040        G2frame.dataFrame.SetTitle('Masks')
3041        G2frame.Image = G2frame.PatternTree.GetItemParent(item)
3042        data = G2frame.PatternTree.GetItemPyData(item)
3043        G2imG.UpdateMasks(G2frame,data)
3044        G2plt.PlotImage(G2frame)
3045    elif G2frame.PatternTree.GetItemText(item) == 'Stress/Strain':
3046        G2frame.dataFrame.SetTitle('Stress/Strain')
3047        G2frame.Image = G2frame.PatternTree.GetItemParent(item)
3048        data = G2frame.PatternTree.GetItemPyData(item)
3049        G2plt.PlotImage(G2frame)
3050        G2plt.PlotStrain(G2frame,data,newPlot=True)
3051        G2imG.UpdateStressStrain(G2frame,data)
3052    elif G2frame.PatternTree.GetItemText(item) == 'PDF Controls':
3053        G2frame.PatternId = G2frame.PatternTree.GetItemParent(item)
3054        for i in G2frame.ExportPDF: i.Enable(True)
3055        data = G2frame.PatternTree.GetItemPyData(item)
3056        G2pdG.UpdatePDFGrid(G2frame,data)
3057        G2plt.PlotISFG(G2frame,type='I(Q)')
3058        G2plt.PlotISFG(G2frame,type='S(Q)')
3059        G2plt.PlotISFG(G2frame,type='F(Q)')
3060        G2plt.PlotISFG(G2frame,type='G(R)')
3061    elif G2frame.PatternTree.GetItemText(item) == 'Peak List':
3062        G2frame.PatternId = G2frame.PatternTree.GetItemParent(item)
3063        for i in G2frame.ExportPeakList: i.Enable(True)
3064        data = G2frame.PatternTree.GetItemPyData(item)
3065#patch
3066        if 'list' in str(type(data)):
3067            data = {'peaks':data,'sigDict':{}}
3068            G2frame.PatternTree.SetItemPyData(item,data)
3069#end patch
3070        G2pdG.UpdatePeakGrid(G2frame,data)
3071        G2plt.PlotPatterns(G2frame)
3072    elif G2frame.PatternTree.GetItemText(item) == 'Background':
3073        G2frame.PatternId = G2frame.PatternTree.GetItemParent(item)
3074        data = G2frame.PatternTree.GetItemPyData(item)
3075        G2pdG.UpdateBackground(G2frame,data)
3076        G2plt.PlotPatterns(G2frame)
3077    elif G2frame.PatternTree.GetItemText(item) == 'Limits':
3078        G2frame.PatternId = G2frame.PatternTree.GetItemParent(item)
3079        datatype = G2frame.PatternTree.GetItemText(G2frame.PatternId)[:4]
3080        data = G2frame.PatternTree.GetItemPyData(item)
3081        G2pdG.UpdateLimitsGrid(G2frame,data,datatype)
3082        G2plt.PlotPatterns(G2frame,plotType=datatype)
3083    elif G2frame.PatternTree.GetItemText(item) == 'Instrument Parameters':
3084        G2frame.PatternId = G2frame.PatternTree.GetItemParent(item)
3085        data = G2frame.PatternTree.GetItemPyData(item)[0]
3086        G2pdG.UpdateInstrumentGrid(G2frame,data)
3087        if 'P' in data['Type'][0]:          #powder data only
3088            G2plt.PlotPeakWidths(G2frame)
3089    elif G2frame.PatternTree.GetItemText(item) == 'Models':
3090        G2frame.PatternId = G2frame.PatternTree.GetItemParent(item)
3091        data = G2frame.PatternTree.GetItemPyData(item)
3092        G2pdG.UpdateModelsGrid(G2frame,data)
3093        G2plt.PlotPatterns(G2frame,plotType='SASD')
3094        if len(data['Size']['Distribution']):
3095            G2plt.PlotSASDSizeDist(G2frame)
3096    elif G2frame.PatternTree.GetItemText(item) == 'Substances':
3097        G2frame.PatternId = G2frame.PatternTree.GetItemParent(item)
3098        data = G2frame.PatternTree.GetItemPyData(item)
3099        G2pdG.UpdateSubstanceGrid(G2frame,data)
3100    elif G2frame.PatternTree.GetItemText(item) == 'Sample Parameters':
3101        G2frame.PatternId = G2frame.PatternTree.GetItemParent(item)
3102        data = G2frame.PatternTree.GetItemPyData(item)
3103        datatype = G2frame.PatternTree.GetItemPyData(G2frame.PatternId)[2][:4]
3104
3105        if 'Temperature' not in data:           #temp fix for old gpx files
3106            data = {'Scale':[1.0,True],'Type':'Debye-Scherrer','Absorption':[0.0,False],'DisplaceX':[0.0,False],
3107                'DisplaceY':[0.0,False],'Diffuse':[],'Temperature':300.,'Pressure':1.0,
3108                    'FreePrm1':0.,'FreePrm2':0.,'FreePrm3':0.,
3109                    'Gonio. radius':200.0}
3110            G2frame.PatternTree.SetItemPyData(item,data)
3111   
3112        G2pdG.UpdateSampleGrid(G2frame,data)
3113        G2plt.PlotPatterns(G2frame,plotType=datatype)
3114    elif G2frame.PatternTree.GetItemText(item) == 'Index Peak List':
3115        G2frame.PatternId = G2frame.PatternTree.GetItemParent(item)
3116        for i in G2frame.ExportPeakList: i.Enable(True)
3117        data = G2frame.PatternTree.GetItemPyData(item)
3118#patch
3119        if len(data) != 2:
3120            data = [data,[]]
3121            G2frame.PatternTree.SetItemPyData(item,data)
3122#end patch
3123        G2pdG.UpdateIndexPeaksGrid(G2frame,data)
3124        if 'PKS' in G2frame.PatternTree.GetItemText(G2frame.PatternId):
3125            G2plt.PlotPowderLines(G2frame)
3126        else:
3127            G2plt.PlotPatterns(G2frame)
3128    elif G2frame.PatternTree.GetItemText(item) == 'Unit Cells List':
3129        G2frame.PatternId = G2frame.PatternTree.GetItemParent(item)
3130        data = G2frame.PatternTree.GetItemPyData(item)
3131        if not data:
3132            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
3133            data.append([0,0,0,0,0,0,0,0,0,0,0,0,0,0])      #Bravais lattice flags
3134            data.append([])                                 #empty cell list
3135            data.append([])                                 #empty dmin
3136            data.append({})                                 #empty superlattice stuff
3137            G2frame.PatternTree.SetItemPyData(item,data)                             
3138#patch
3139        if len(data) < 5:
3140            data.append({'Use':False,'ModVec':[0,0,0.1],'maxH':1,'ssSymb':''})                                 #empty superlattice stuff
3141            G2frame.PatternTree.SetItemPyData(item,data) 
3142#end patch
3143        G2pdG.UpdateUnitCellsGrid(G2frame,data)
3144        if 'PKS' in G2frame.PatternTree.GetItemText(G2frame.PatternId):
3145            G2plt.PlotPowderLines(G2frame)
3146        else:
3147            G2plt.PlotPatterns(G2frame)
3148    elif G2frame.PatternTree.GetItemText(item) == 'Reflection Lists':   #powder reflections
3149        G2frame.PatternId = G2frame.PatternTree.GetItemParent(item)
3150        data = G2frame.PatternTree.GetItemPyData(item)
3151        G2frame.RefList = ''
3152        if len(data):
3153            G2frame.RefList = data.keys()[0]
3154        G2pdG.UpdateReflectionGrid(G2frame,data)
3155        G2plt.PlotPatterns(G2frame)
3156    elif G2frame.PatternTree.GetItemText(item) == 'Reflection List':    #HKLF reflections
3157        G2frame.PatternId = G2frame.PatternTree.GetItemParent(item)
3158        name = G2frame.PatternTree.GetItemText(G2frame.PatternId)
3159        data = G2frame.PatternTree.GetItemPyData(G2frame.PatternId)
3160        G2pdG.UpdateReflectionGrid(G2frame,data,HKLF=True,Name=name)
3161
3162    if G2frame.PickId:
3163        G2frame.PickIdText = G2frame.GetTreeItemsList(G2frame.PickId)
3164    G2frame.dataFrame.Raise()
3165
3166def SetDataMenuBar(G2frame,menu=None):
3167    '''Set the menu for the data frame. On the Mac put this
3168    menu for the data tree window instead.
3169
3170    Note that data frame items do not have menus, for these (menu=None)
3171    display a blank menu or on the Mac display the standard menu for
3172    the data tree window.
3173    '''
3174    if sys.platform == "darwin":
3175        if menu is None:
3176            G2frame.SetMenuBar(G2frame.GSASIIMenu)
3177        else:
3178            G2frame.SetMenuBar(menu)
3179    else:
3180        if menu is None:
3181            G2frame.dataFrame.SetMenuBar(G2frame.dataFrame.BlankMenu)
3182        else:
3183            G2frame.dataFrame.SetMenuBar(menu)
3184
3185def HowDidIgetHere():
3186    '''Show a traceback with calls that brought us to the current location.
3187    Used for debugging.
3188    '''
3189    import traceback
3190    print 70*'*'   
3191    for i in traceback.format_list(traceback.extract_stack()[:-1]): print(i.strip.rstrip())
3192    print 70*'*'   
3193       
Note: See TracBrowser for help on using the repository browser.