source: trunk/GSASIIgrid.py @ 859

Last change on this file since 859 was 859, checked in by vondreele, 9 years ago

still more rigid body fixes
add thermal motion models
allow copy of RB parms
import of rb models from gpx files
seq refinement results fixes

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