source: trunk/GSASIIgrid.py @ 2172

Last change on this file since 2172 was 2172, checked in by vondreele, 6 years ago

add new dialog for DIFFaX controls (now empty)
fix layer pair plotting - allow shifting of one layer vs the reference
updates plot & Transitions values
fix hard copy plot error - structure drawings were flipped up/down!

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