source: trunk/GSASIIgrid.py @ 852

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

rigid body changes

  • Property svn:eol-style set to native
  • Property svn:keywords set to Date Author Revision URL Id
File size: 100.9 KB
Line 
1# -*- coding: utf-8 -*-
2#GSASIIgrid - data display routines
3########### SVN repository information ###################
4# $Date: 2013-02-18 16:49:45 +0000 (Mon, 18 Feb 2013) $
5# $Author: vondreele $
6# $Revision: 852 $
7# $URL: trunk/GSASIIgrid.py $
8# $Id: GSASIIgrid.py 852 2013-02-18 16:49:45Z 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: 852 $")
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,
115] = [wx.NewId() for item in range(7)]
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_AUTOFINDRESRB, kind=wx.ITEM_NORMAL,text='Auto find residues',
1259            help='Auto find of residue RBs in macromolecule')
1260        self.RigidBodiesEdit.Append(id=wxID_ASSIGNATMS2RB, kind=wx.ITEM_NORMAL,text='Assign atoms to rigid body',
1261            help='Select & position rigid body in structure for existing atoms')
1262        self.RigidBodiesEdit.Append(id=wxID_GLOBALRESREFINE, kind=wx.ITEM_NORMAL,text='Global residue refine',
1263            help='Global setting of residue RB refinement flags')
1264        self.RigidBodiesEdit.Append(id=wxID_RBREMOVEALL, kind=wx.ITEM_NORMAL,text='Remove all rigid bodies',
1265            help='Remove all rigid body assignment for atoms')
1266        self.PostfillDataMenu()
1267           
1268# end of GSAS-II menu definitions
1269       
1270    def _init_ctrls(self, parent,name=None,size=None,pos=None):
1271        wx.Frame.__init__(self,parent=parent,
1272            style=wx.DEFAULT_FRAME_STYLE ^ wx.CLOSE_BOX | wx.FRAME_FLOAT_ON_PARENT ,
1273            size=size,pos=pos,title='GSAS-II data display')
1274        self._init_menus()
1275        if name:
1276            self.SetLabel(name)
1277        self.Show()
1278       
1279    def __init__(self,parent,frame,data=None,name=None, size=None,pos=None):
1280        self.G2frame = frame
1281        self._init_ctrls(parent,name,size,pos)
1282        self.data = data
1283        clientSize = wx.ClientDisplayRect()
1284        Size = self.GetSize()
1285        xPos = clientSize[2]-Size[0]
1286        self.SetPosition(wx.Point(xPos,clientSize[1]+250))
1287        self.AtomGrid = []
1288        self.selectedRow = 0
1289       
1290    def setSizePosLeft(self,Width):
1291        clientSize = wx.ClientDisplayRect()
1292        Width[1] = min(Width[1],clientSize[2]-300)
1293        Width[0] = max(Width[0],300)
1294        self.SetSize(Width)
1295#        self.SetPosition(wx.Point(clientSize[2]-Width[0],clientSize[1]+250))
1296       
1297    def Clear(self):
1298        self.ClearBackground()
1299        self.DestroyChildren()
1300                   
1301################################################################################
1302#####  GSNotebook
1303################################################################################           
1304       
1305class GSNoteBook(wx.Notebook):
1306    def __init__(self, parent, name='',size = None):
1307        wx.Notebook.__init__(self, parent, -1, name=name, style= wx.BK_TOP)
1308        if size: self.SetSize(size)
1309                                                     
1310    def Clear(self):       
1311        GSNoteBook.DeleteAllPages(self)
1312       
1313    def FindPage(self,name):
1314        numPage = self.GetPageCount()
1315        for page in range(numPage):
1316            if self.GetPageText(page) == name:
1317                return page
1318       
1319################################################################################
1320#####  GSGrid
1321################################################################################           
1322       
1323class GSGrid(wg.Grid):
1324    def __init__(self, parent, name=''):
1325        wg.Grid.__init__(self,parent,-1,name=name)                   
1326        self.SetSize(parent.GetClientSize())
1327           
1328    def Clear(self):
1329        wg.Grid.ClearGrid(self)
1330       
1331    def SetCellStyle(self,r,c,color="white",readonly=True):
1332        self.SetCellBackgroundColour(r,c,color)
1333        self.SetReadOnly(r,c,isReadOnly=readonly)
1334       
1335    def GetSelection(self):
1336        #this is to satisfy structure drawing stuff in G2plt when focus changes
1337        return None
1338                                               
1339################################################################################
1340#####  Table
1341################################################################################           
1342       
1343class Table(wg.PyGridTableBase):
1344    def __init__(self, data=[], rowLabels=None, colLabels=None, types = None):
1345        wg.PyGridTableBase.__init__(self)
1346        self.colLabels = colLabels
1347        self.rowLabels = rowLabels
1348        self.dataTypes = types
1349        self.data = data
1350       
1351    def AppendRows(self, numRows=1):
1352        self.data.append([])
1353        return True
1354       
1355    def CanGetValueAs(self, row, col, typeName):
1356        if self.dataTypes:
1357            colType = self.dataTypes[col].split(':')[0]
1358            if typeName == colType:
1359                return True
1360            else:
1361                return False
1362        else:
1363            return False
1364
1365    def CanSetValueAs(self, row, col, typeName):
1366        return self.CanGetValueAs(row, col, typeName)
1367
1368    def DeleteRow(self,pos):
1369        data = self.GetData()
1370        self.SetData([])
1371        new = []
1372        for irow,row in enumerate(data):
1373            if irow <> pos:
1374                new.append(row)
1375        self.SetData(new)
1376       
1377    def GetColLabelValue(self, col):
1378        if self.colLabels:
1379            return self.colLabels[col]
1380           
1381    def GetData(self):
1382        data = []
1383        for row in range(self.GetNumberRows()):
1384            data.append(self.GetRowValues(row))
1385        return data
1386       
1387    def GetNumberCols(self):
1388        try:
1389            return len(self.colLabels)
1390        except TypeError:
1391            return None
1392       
1393    def GetNumberRows(self):
1394        return len(self.data)
1395       
1396    def GetRowLabelValue(self, row):
1397        if self.rowLabels:
1398            return self.rowLabels[row]
1399       
1400    def GetColValues(self, col):
1401        data = []
1402        for row in range(self.GetNumberRows()):
1403            data.append(self.GetValue(row, col))
1404        return data
1405       
1406    def GetRowValues(self, row):
1407        data = []
1408        for col in range(self.GetNumberCols()):
1409            data.append(self.GetValue(row, col))
1410        return data
1411       
1412    def GetTypeName(self, row, col):
1413        try:
1414            return self.dataTypes[col]
1415        except TypeError:
1416            return None
1417
1418    def GetValue(self, row, col):
1419        try:
1420            return self.data[row][col]
1421        except IndexError:
1422            return None
1423           
1424    def InsertRows(self, pos, rows):
1425        for row in range(rows):
1426            self.data.insert(pos,[])
1427            pos += 1
1428       
1429    def IsEmptyCell(self,row,col):
1430        try:
1431            return not self.data[row][col]
1432        except IndexError:
1433            return True
1434       
1435    def OnKeyPress(self, event):
1436        dellist = self.GetSelectedRows()
1437        if event.GetKeyCode() == wx.WXK_DELETE and dellist:
1438            grid = self.GetView()
1439            for i in dellist: grid.DeleteRow(i)
1440               
1441    def SetColLabelValue(self, col, label):
1442        numcols = self.GetNumberCols()
1443        if col > numcols-1:
1444            self.colLabels.append(label)
1445        else:
1446            self.colLabels[col]=label
1447       
1448    def SetData(self,data):
1449        for row in range(len(data)):
1450            self.SetRowValues(row,data[row])
1451               
1452    def SetRowLabelValue(self, row, label):
1453        self.rowLabels[row]=label
1454           
1455    def SetRowValues(self,row,data):
1456        self.data[row] = data
1457           
1458    def SetValue(self, row, col, value):
1459        def innerSetValue(row, col, value):
1460            try:
1461                self.data[row][col] = value
1462            except TypeError:
1463                return
1464            except IndexError:
1465                print row,col,value
1466                # add a new row
1467                if row > self.GetNumberRows():
1468                    self.data.append([''] * self.GetNumberCols())
1469                elif col > self.GetNumberCols():
1470                    for row in range(self.GetNumberRows):
1471                        self.data[row].append('')
1472                print self.data
1473                self.data[row][col] = value
1474        innerSetValue(row, col, value)
1475       
1476################################################################################
1477#### Help
1478################################################################################
1479
1480def ShowHelp(helpType,frame):
1481    '''Called to bring up a web page for documentation.'''
1482    global htmlFirstUse
1483    # look up a definition for help info from dict
1484    helplink = helpLocDict.get(helpType)
1485    if helplink is None:
1486        # no defined link to use, create a default based on key
1487        helplink = 'gsasII.html#'+helpType.replace(' ','_')
1488    helplink = os.path.join(path2GSAS2,'help',helplink)
1489    if helpMode == 'internal':
1490        try:
1491            htmlPanel.LoadFile(helplink)
1492            htmlFrame.Raise()
1493        except:
1494            htmlFrame = wx.Frame(frame, -1, size=(610, 510))
1495            htmlFrame.Show(True)
1496            htmlFrame.SetTitle("HTML Window") # N.B. reset later in LoadFile
1497            htmlPanel = MyHtmlPanel(htmlFrame,-1)
1498            htmlPanel.LoadFile(helplink)
1499    else:
1500        pfx = "file://"
1501        if sys.platform.lower().startswith('win'):
1502            pfx = ''
1503        if htmlFirstUse:
1504            webbrowser.open_new(pfx+helplink)
1505            htmlFirstUse = False
1506        else:
1507            webbrowser.open(pfx+helplink, new=0, autoraise=True)
1508
1509################################################################################
1510#####  Notebook
1511################################################################################           
1512       
1513def UpdateNotebook(G2frame,data):       
1514    if data:
1515        G2frame.dataFrame.SetLabel('Notebook')
1516        G2frame.dataDisplay = wx.TextCtrl(parent=G2frame.dataFrame,size=G2frame.dataFrame.GetClientSize(),
1517            style=wx.TE_MULTILINE|wx.TE_PROCESS_ENTER | wx.TE_DONTWRAP)
1518        for line in data:
1519            G2frame.dataDisplay.AppendText(line+"\n")
1520            G2frame.dataDisplay.AppendText('Notebook entry @ '+time.ctime()+"\n")
1521           
1522################################################################################
1523#####  Controls
1524################################################################################           
1525       
1526def UpdateControls(G2frame,data):
1527    #patch
1528    if 'deriv type' not in data:
1529        data = {}
1530        data['deriv type'] = 'analytic Hessian'
1531        data['min dM/M'] = 0.0001
1532        data['shift factor'] = 1.
1533        data['max cyc'] = 3       
1534        data['F**2'] = True
1535        data['minF/sig'] = 0
1536    if 'shift factor' not in data:
1537        data['shift factor'] = 1.
1538    if 'max cyc' not in data:
1539        data['max cyc'] = 3
1540    if 'F**2' not in data:
1541        data['F**2'] = True
1542        data['minF/sig'] = 0
1543    #end patch
1544
1545    def SeqSizer():
1546       
1547        def OnSelectData(event):
1548            choices = ['All',]+GetPatternTreeDataNames(G2frame,['PWDR',])
1549            sel = []
1550            if 'Seq Data' in data:
1551                for item in data['Seq Data']:
1552                    sel.append(choices.index(item))
1553            names = []
1554            dlg = wx.MultiChoiceDialog(G2frame,'Select data:','Sequential refinement',choices)
1555            dlg.SetSelections(sel)
1556            if dlg.ShowModal() == wx.ID_OK:
1557                sel = dlg.GetSelections()
1558                for i in sel: names.append(choices[i])
1559                if 'All' in names:
1560                    names = choices[1:]
1561                data['Seq Data'] = names               
1562            dlg.Destroy()
1563            reverseSel.Enable(True)
1564           
1565        def OnReverse(event):
1566            data['Reverse Seq'] = reverseSel.GetValue()
1567                   
1568        seqSizer = wx.BoxSizer(wx.HORIZONTAL)
1569        seqSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Sequential Refinement Powder Data: '),0,wx.ALIGN_CENTER_VERTICAL)
1570        selSeqData = wx.Button(G2frame.dataDisplay,-1,label=' Select data')
1571        selSeqData.Bind(wx.EVT_BUTTON,OnSelectData)
1572        seqSizer.Add(selSeqData,0,wx.ALIGN_CENTER_VERTICAL)
1573        seqSizer.Add((5,0),0)
1574        reverseSel = wx.CheckBox(G2frame.dataDisplay,-1,label=' Reverse order?')
1575        reverseSel.Bind(wx.EVT_CHECKBOX,OnReverse)
1576        if 'Seq Data' not in data:
1577            reverseSel.Enable(False)
1578        if 'Reverse Seq' in data:
1579            reverseSel.SetValue(data['Reverse Seq'])
1580        seqSizer.Add(reverseSel,0,wx.ALIGN_CENTER_VERTICAL)
1581        return seqSizer
1582       
1583    def LSSizer():       
1584       
1585        def OnDerivType(event):
1586            data['deriv type'] = derivSel.GetValue()
1587            derivSel.SetValue(data['deriv type'])
1588            wx.CallAfter(UpdateControls,G2frame,data)
1589           
1590        def OnConvergence(event):
1591            try:
1592                value = max(1.e-9,min(1.0,float(Cnvrg.GetValue())))
1593            except ValueError:
1594                value = 0.0001
1595            data['min dM/M'] = value
1596            Cnvrg.SetValue('%.2g'%(value))
1597           
1598        def OnMaxCycles(event):
1599            data['max cyc'] = int(maxCyc.GetValue())
1600            maxCyc.SetValue(str(data['max cyc']))
1601                       
1602        def OnFactor(event):
1603            try:
1604                value = min(max(float(Factr.GetValue()),0.00001),100.)
1605            except ValueError:
1606                value = 1.0
1607            data['shift factor'] = value
1608            Factr.SetValue('%.5f'%(value))
1609           
1610        def OnFsqRef(event):
1611            data['F**2'] = fsqRef.GetValue()
1612       
1613        def OnMinSig(event):
1614            try:
1615                value = min(max(float(minSig.GetValue()),0.),5.)
1616            except ValueError:
1617                value = 1.0
1618            data['minF/sig'] = value
1619            minSig.SetValue('%.2f'%(value))
1620
1621        LSSizer = wx.FlexGridSizer(cols=4,vgap=5,hgap=5)
1622        LSSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Refinement derivatives: '),0,wx.ALIGN_CENTER_VERTICAL)
1623        Choice=['analytic Jacobian','numeric','analytic Hessian']
1624        derivSel = wx.ComboBox(parent=G2frame.dataDisplay,value=data['deriv type'],choices=Choice,
1625            style=wx.CB_READONLY|wx.CB_DROPDOWN)
1626        derivSel.SetValue(data['deriv type'])
1627        derivSel.Bind(wx.EVT_COMBOBOX, OnDerivType)
1628           
1629        LSSizer.Add(derivSel,0,wx.ALIGN_CENTER_VERTICAL)
1630        LSSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Min delta-M/M: '),0,wx.ALIGN_CENTER_VERTICAL)
1631        Cnvrg = wx.TextCtrl(G2frame.dataDisplay,-1,value='%.2g'%(data['min dM/M']),style=wx.TE_PROCESS_ENTER)
1632        Cnvrg.Bind(wx.EVT_TEXT_ENTER,OnConvergence)
1633        Cnvrg.Bind(wx.EVT_KILL_FOCUS,OnConvergence)
1634        LSSizer.Add(Cnvrg,0,wx.ALIGN_CENTER_VERTICAL)
1635        if 'Hessian' in data['deriv type']:
1636            LSSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Max cycles: '),0,wx.ALIGN_CENTER_VERTICAL)
1637            Choice = ['0','1','2','3','5','10','15','20']
1638            maxCyc = wx.ComboBox(parent=G2frame.dataDisplay,value=str(data['max cyc']),choices=Choice,
1639                style=wx.CB_READONLY|wx.CB_DROPDOWN)
1640            maxCyc.SetValue(str(data['max cyc']))
1641            maxCyc.Bind(wx.EVT_COMBOBOX, OnMaxCycles)
1642            LSSizer.Add(maxCyc,0,wx.ALIGN_CENTER_VERTICAL)
1643        else:
1644            LSSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Initial shift factor: '),0,wx.ALIGN_CENTER_VERTICAL)
1645            Factr = wx.TextCtrl(G2frame.dataDisplay,-1,value='%.5f'%(data['shift factor']),style=wx.TE_PROCESS_ENTER)
1646            Factr.Bind(wx.EVT_TEXT_ENTER,OnFactor)
1647            Factr.Bind(wx.EVT_KILL_FOCUS,OnFactor)
1648            LSSizer.Add(Factr,0,wx.ALIGN_CENTER_VERTICAL)
1649        if G2frame.Sngl:
1650            LSSizer.Add((1,0),)
1651            LSSizer.Add((1,0),)
1652            fsqRef = wx.CheckBox(G2frame.dataDisplay,-1,label='Refine HKLF as F^2? ')
1653            fsqRef.SetValue(data['F**2'])
1654            fsqRef.Bind(wx.EVT_CHECKBOX,OnFsqRef)
1655            LSSizer.Add(fsqRef,0,wx.ALIGN_CENTER_VERTICAL)
1656            LSSizer.Add(wx.StaticText(G2frame.dataDisplay,-1,label='Min obs/sig (0-5): '),0,wx.ALIGN_CENTER_VERTICAL)
1657            minSig = wx.TextCtrl(G2frame.dataDisplay,-1,value='%.2f'%(data['minF/sig']),style=wx.TE_PROCESS_ENTER)
1658            minSig.Bind(wx.EVT_TEXT_ENTER,OnMinSig)
1659            minSig.Bind(wx.EVT_KILL_FOCUS,OnMinSig)
1660            LSSizer.Add(minSig,0,wx.ALIGN_CENTER_VERTICAL)
1661        return LSSizer
1662       
1663    if G2frame.dataDisplay:
1664        G2frame.dataDisplay.Destroy()
1665    if not G2frame.dataFrame.GetStatusBar():
1666        Status = G2frame.dataFrame.CreateStatusBar()
1667        Status.SetStatusText('')
1668    G2frame.dataFrame.SetLabel('Controls')
1669    G2frame.dataDisplay = wx.Panel(G2frame.dataFrame)
1670    SetDataMenuBar(G2frame,G2frame.dataFrame.ControlsMenu)
1671    mainSizer = wx.BoxSizer(wx.VERTICAL)
1672    mainSizer.Add((5,5),0)
1673    mainSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Refinement Controls:'),0,wx.ALIGN_CENTER_VERTICAL)   
1674    mainSizer.Add(LSSizer())
1675    mainSizer.Add((5,5),0)
1676    mainSizer.Add(SeqSizer())
1677    mainSizer.Add((5,5),0)
1678       
1679    mainSizer.Layout()   
1680    G2frame.dataDisplay.SetSizer(mainSizer)
1681    G2frame.dataDisplay.SetSize(mainSizer.Fit(G2frame.dataFrame))
1682    G2frame.dataFrame.setSizePosLeft(mainSizer.Fit(G2frame.dataFrame))
1683     
1684################################################################################
1685#####  Comments
1686################################################################################           
1687       
1688def UpdateComments(G2frame,data):                   
1689    G2frame.dataFrame.SetLabel('Comments')
1690    G2frame.dataDisplay = wx.TextCtrl(parent=G2frame.dataFrame,size=G2frame.dataFrame.GetClientSize(),
1691        style=wx.TE_MULTILINE|wx.TE_PROCESS_ENTER | wx.TE_DONTWRAP)
1692    for line in data:
1693        if line[-1] == '\n':
1694            G2frame.dataDisplay.AppendText(line)
1695        else:
1696            G2frame.dataDisplay.AppendText(line+'\n')
1697           
1698################################################################################
1699#####  Sequential Results
1700################################################################################           
1701       
1702def UpdateSeqResults(G2frame,data):
1703    """
1704    input:
1705        data - dictionary
1706            'histNames' - list of histogram names in order as processed by Sequential Refinement
1707            'varyList' - list of variables - identical over all refinements insequence
1708            'histName' - dictionaries for all data sets processed:
1709                'variables'- result[0] from leastsq call
1710                'varyList' - list of variables; same as above
1711                'sig' - esds for variables
1712                'covMatrix' - covariance matrix from individual refinement
1713                'title' - histogram name; same as dict item name
1714                'newAtomDict' - new atom parameters after shifts applied
1715                'newCellDict' - new cell parameters after shifts to A0-A5 applied'
1716    """
1717    if not data:
1718        print 'No sequential refinement results'
1719        return
1720    histNames = data['histNames']
1721       
1722    def GetSampleParms():
1723        sampleParmDict = {'Temperature':[],'Pressure':[],'Humidity':[],'Voltage':[],'Force':[],}
1724        sampleParm = {}
1725        for name in histNames:
1726            Id = GetPatternTreeItemId(G2frame,G2frame.root,name)
1727            sampleData = G2frame.PatternTree.GetItemPyData(GetPatternTreeItemId(G2frame,Id,'Sample Parameters'))
1728            for item in sampleParmDict:
1729                sampleParmDict[item].append(sampleData[item])
1730        for item in sampleParmDict:
1731            frstValue = sampleParmDict[item][0]
1732            if np.any(np.array(sampleParmDict[item])-frstValue):
1733                sampleParm[item] = sampleParmDict[item]           
1734        return sampleParm
1735           
1736    def GetRwps():
1737        Rwps = []
1738        for name in histNames:
1739            Rwps.append(data[name]['Rvals']['Rwp'])
1740        return Rwps
1741           
1742    def GetSigData(parm):
1743        sigData = []
1744        for name in histNames:
1745            sigList = data[name]['sig']
1746            if colLabels[parm] in atomList:
1747                sigData.append(sigList[colLabels.index(atomList[colLabels[parm]])])
1748            elif colLabels[parm] in cellList:
1749                sigData.append(sigList[colLabels.index(cellList[colLabels[parm]])])
1750            else:
1751                sigData.append(sigList[parm])
1752        return sigData
1753   
1754    def Select(event):
1755        cols = G2frame.dataDisplay.GetSelectedCols()
1756        rows = G2frame.dataDisplay.GetSelectedRows()
1757        if cols:
1758            plotData = []
1759            plotSig = []
1760            plotNames = []
1761            for col in cols:
1762                plotData.append(G2frame.SeqTable.GetColValues(col))
1763                plotSig.append(GetSigData(col))
1764                plotNames.append(G2frame.SeqTable.GetColLabelValue(col))
1765            plotData = np.array(plotData)
1766            G2plt.PlotSeq(G2frame,plotData,plotSig,plotNames,sampleParms)
1767        elif rows:
1768            name = histNames[rows[0]]
1769            G2plt.PlotCovariance(G2frame,Data=data[name])
1770           
1771    def OnSaveSelSeq(event):       
1772        cols = G2frame.dataDisplay.GetSelectedCols()
1773        if cols:
1774            numRows = G2frame.SeqTable.GetNumberRows()
1775            dataNames = []
1776            saveNames = [G2frame.SeqTable.GetRowLabelValue(r) for r in range(numRows)]
1777            saveData = []
1778            for col in cols:
1779                dataNames.append(G2frame.SeqTable.GetColLabelValue(col))
1780                saveData.append(zip(G2frame.SeqTable.GetColValues(col),GetSigData(col)))
1781            lenName = len(saveNames[0])
1782            saveData = np.swapaxes(np.array(saveData),0,1)
1783            dlg = wx.FileDialog(G2frame, 'Choose text output file for your selection', '.', '', 
1784                'Text output file (*.txt)|*.txt',wx.FD_SAVE|wx.FD_OVERWRITE_PROMPT|wx.CHANGE_DIR)
1785            try:
1786                if dlg.ShowModal() == wx.ID_OK:
1787                    SeqTextFile = dlg.GetPath()
1788                    SeqTextFile = G2IO.FileDlgFixExt(dlg,SeqTextFile)
1789                    SeqFile = open(SeqTextFile,'w')
1790                    line = %s  '%('name'.center(lenName))
1791                    for item in dataNames:
1792                        line += ' %12s %12s '%(item.center(12),'esd'.center(12))
1793                    line += '\n'
1794                    SeqFile.write(line)
1795                    for i,item in enumerate(saveData):
1796                        line = " '%s' "%(saveNames[i])
1797                        for val,esd in item:
1798                            line += ' %12.6f %12.6f '%(val,esd)
1799                        line += '\n'
1800                        SeqFile.write(line)
1801                    SeqFile.close()
1802            finally:
1803                dlg.Destroy()
1804           
1805               
1806    if G2frame.dataDisplay:
1807        G2frame.dataDisplay.Destroy()
1808    cellList = {}
1809    newCellDict = data[histNames[0]]['newCellDict']
1810    for item in newCellDict:
1811        if item in data['varyList']:
1812            cellList[newCellDict[item][0]] = item
1813    atomList = {}
1814    newAtomDict = data[histNames[0]]['newAtomDict']
1815    for item in newAtomDict:
1816        if item in data['varyList']:
1817            atomList[newAtomDict[item][0]] = item
1818    sampleParms = GetSampleParms()
1819    Rwps = GetRwps()
1820    SetDataMenuBar(G2frame,G2frame.dataFrame.SequentialMenu)
1821    G2frame.dataFrame.SetLabel('Sequental refinement results')
1822    G2frame.dataFrame.CreateStatusBar()
1823    G2frame.dataFrame.Bind(wx.EVT_MENU, OnSaveSelSeq, id=wxID_SAVESEQSEL)
1824    colLabels = ['Rwp',]+data['varyList']+atomList.keys()+cellList.keys()
1825    Types = (len(data['varyList']+atomList.keys()+cellList.keys())+1)*[wg.GRID_VALUE_FLOAT,]
1826    seqList = [[Rwps[i],]+list(data[name]['variables']) for i,name in enumerate(histNames)]   
1827    for i,item in enumerate(seqList):
1828        newAtomDict = data[histNames[i]]['newAtomDict']
1829        newCellDict = data[histNames[i]]['newCellDict']
1830        item += [newAtomDict[atomList[parm]][1] for parm in atomList.keys()]
1831        item += [newCellDict[cellList[parm]][1] for parm in cellList.keys()]
1832    G2frame.SeqTable = Table(seqList,colLabels=colLabels,rowLabels=histNames,types=Types)
1833    G2frame.dataDisplay = GSGrid(parent=G2frame.dataFrame)
1834    G2frame.dataDisplay.SetTable(G2frame.SeqTable, True)
1835    G2frame.dataDisplay.EnableEditing(False)
1836    G2frame.dataDisplay.Bind(wg.EVT_GRID_LABEL_LEFT_DCLICK, Select)
1837    G2frame.dataDisplay.SetRowLabelSize(8*len(histNames[0]))       #pretty arbitrary 8
1838    G2frame.dataDisplay.SetMargins(0,0)
1839    G2frame.dataDisplay.AutoSizeColumns(True)
1840    G2frame.dataFrame.setSizePosLeft([700,350])
1841       
1842################################################################################
1843#####  Main PWDR panel
1844################################################################################           
1845       
1846def UpdatePWHKPlot(G2frame,kind,item):
1847
1848    def OnErrorAnalysis(event):
1849        G2plt.PlotDeltSig(G2frame,kind)
1850       
1851    def OnWtFactor(event):
1852        try:
1853            val = float(wtval.GetValue())
1854        except ValueError:
1855            val = data[0]['wtFactor']
1856        data[0]['wtFactor'] = val
1857        wtval.SetValue('%.3f'%(val))
1858           
1859    data = G2frame.PatternTree.GetItemPyData(item)
1860    if 'wtFactor' not in data[0]:
1861        data[0] = {'wtFactor':1.0}
1862    if G2frame.dataDisplay:
1863        G2frame.dataDisplay.Destroy()
1864    SetDataMenuBar(G2frame,G2frame.dataFrame.ErrorMenu)
1865    G2frame.dataFrame.Bind(wx.EVT_MENU,OnErrorAnalysis, id=wxID_PWDANALYSIS)
1866    G2frame.dataDisplay = wx.Panel(G2frame.dataFrame)
1867   
1868    mainSizer = wx.BoxSizer(wx.VERTICAL)
1869    mainSizer.Add((5,5),)
1870    wtSizer = wx.BoxSizer(wx.HORIZONTAL)
1871    wtSizer.Add(wx.StaticText(G2frame.dataDisplay,-1,' Weight factor: '),0,wx.ALIGN_CENTER_VERTICAL)
1872    wtval = wx.TextCtrl(G2frame.dataDisplay,-1,'%.3f'%(data[0]['wtFactor']),style=wx.TE_PROCESS_ENTER)
1873    wtval.Bind(wx.EVT_TEXT_ENTER,OnWtFactor)
1874    wtval.Bind(wx.EVT_KILL_FOCUS,OnWtFactor)
1875    wtSizer.Add(wtval,0,wx.ALIGN_CENTER_VERTICAL)
1876    mainSizer.Add(wtSizer)
1877    mainSizer.Layout()   
1878    G2frame.dataDisplay.SetSizer(mainSizer)
1879    G2frame.dataFrame.setSizePosLeft(mainSizer.Fit(G2frame.dataFrame))
1880    G2frame.PatternTree.SetItemPyData(item,data)
1881    if kind == 'PWDR':
1882        G2plt.PlotPatterns(G2frame,newPlot=True)
1883    elif kind == 'HKLF':
1884        G2plt.PlotSngl(G2frame,newPlot=True)
1885                 
1886################################################################################
1887#####  HKLF controls
1888################################################################################           
1889       
1890def UpdateHKLControls(G2frame,data):
1891   
1892    def OnScaleSlider(event):
1893        scale = int(scaleSel.GetValue())/1000.
1894        scaleSel.SetValue(int(scale*1000.))
1895        data['Scale'] = scale*1.
1896        G2plt.PlotSngl(G2frame)
1897       
1898    def OnLayerSlider(event):
1899        layer = layerSel.GetValue()
1900        data['Layer'] = layer
1901        G2plt.PlotSngl(G2frame)
1902       
1903    def OnSelZone(event):
1904        data['Zone'] = zoneSel.GetValue()
1905        izone = zones.index(data['Zone'])
1906        layerSel.SetRange(maxValue=HKLmax[izone],minValue=HKLmin[izone])
1907        G2plt.PlotSngl(G2frame,newPlot=True)
1908       
1909    def OnSelType(event):
1910        data['Type'] = typeSel.GetValue()
1911        G2plt.PlotSngl(G2frame)
1912       
1913    def SetStatusLine():
1914        Status.SetStatusText("")
1915                                     
1916    if G2frame.dataDisplay:
1917        G2frame.dataDisplay.Destroy()
1918    if not G2frame.dataFrame.GetStatusBar():
1919        Status = G2frame.dataFrame.CreateStatusBar()
1920    SetStatusLine()
1921    zones = ['100','010','001']
1922    HKLmax = data['HKLmax']
1923    HKLmin = data['HKLmin']
1924    typeChoices = ['Fosq','Fo','|DFsq|/sig','|DFsq|>sig','|DFsq|>3sig']
1925    G2frame.dataDisplay = wx.Panel(G2frame.dataFrame)
1926    SetDataMenuBar(G2frame)
1927    G2frame.dataFrame.SetTitle('HKL Plot Controls')
1928    mainSizer = wx.BoxSizer(wx.VERTICAL)
1929    mainSizer.Add((5,10),0)
1930   
1931    scaleSizer = wx.BoxSizer(wx.HORIZONTAL)
1932    scaleSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' Scale'),0,
1933        wx.ALIGN_CENTER_VERTICAL|wx.EXPAND)
1934    scaleSel = wx.Slider(parent=G2frame.dataDisplay,maxValue=1000,minValue=1,
1935        style=wx.SL_HORIZONTAL,value=int(data['Scale']*10))
1936    scaleSizer.Add(scaleSel,1,wx.EXPAND|wx.RIGHT|wx.ALIGN_CENTER_VERTICAL)
1937    scaleSel.SetLineSize(10)
1938    scaleSel.SetPageSize(10)
1939    scaleSel.Bind(wx.EVT_SLIDER, OnScaleSlider)
1940    mainSizer.Add(scaleSizer,0,wx.EXPAND|wx.RIGHT)
1941    mainSizer.Add((0,10),0)   
1942   
1943    zoneSizer = wx.BoxSizer(wx.HORIZONTAL)
1944    zoneSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' Zone  '),0,
1945        wx.ALIGN_CENTER_VERTICAL)
1946    zoneSel = wx.ComboBox(parent=G2frame.dataDisplay,value=data['Zone'],choices=['100','010','001'],
1947        style=wx.CB_READONLY|wx.CB_DROPDOWN)
1948    zoneSel.Bind(wx.EVT_COMBOBOX, OnSelZone)
1949    zoneSizer.Add(zoneSel,0,wx.ALIGN_CENTER_VERTICAL)
1950    zoneSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' Plot type  '),0,
1951        wx.ALIGN_CENTER_VERTICAL)       
1952    typeSel = wx.ComboBox(parent=G2frame.dataDisplay,value=data['Type'],choices=typeChoices,
1953        style=wx.CB_READONLY|wx.CB_DROPDOWN)
1954    typeSel.Bind(wx.EVT_COMBOBOX, OnSelType)
1955    zoneSizer.Add(typeSel,0,wx.ALIGN_CENTER_VERTICAL)
1956    zoneSizer.Add((10,0),0)   
1957    mainSizer.Add(zoneSizer,0,wx.EXPAND|wx.RIGHT)
1958    mainSizer.Add((0,10),0)   
1959       
1960    izone = zones.index(data['Zone'])
1961    layerSizer = wx.BoxSizer(wx.HORIZONTAL)
1962    layerSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' Layer'),0,
1963        wx.ALIGN_CENTER_VERTICAL|wx.EXPAND)
1964    layerSel = wx.Slider(parent=G2frame.dataDisplay,maxValue=HKLmax[izone],minValue=HKLmin[izone],
1965        style=wx.SL_HORIZONTAL|wx.SL_AUTOTICKS|wx.SL_LABELS,value=0)
1966    layerSel.SetLineSize(1)
1967    layerSel.SetPageSize(1)
1968    layerSel.Bind(wx.EVT_SLIDER, OnLayerSlider)   
1969    layerSizer.Add(layerSel,1,wx.EXPAND|wx.RIGHT|wx.ALIGN_CENTER_VERTICAL)
1970    layerSizer.Add((10,0),0)   
1971    mainSizer.Add(layerSizer,1,wx.EXPAND|wx.RIGHT)
1972
1973       
1974    mainSizer.Layout()   
1975    G2frame.dataDisplay.SetSizer(mainSizer)
1976    G2frame.dataDisplay.SetSize(mainSizer.Fit(G2frame.dataFrame))
1977    G2frame.dataFrame.setSizePosLeft(mainSizer.Fit(G2frame.dataFrame))
1978
1979################################################################################
1980#####  Pattern tree routines
1981################################################################################           
1982       
1983def GetPatternTreeDataNames(G2frame,dataTypes):
1984    names = []
1985    item, cookie = G2frame.PatternTree.GetFirstChild(G2frame.root)       
1986    while item:
1987        name = G2frame.PatternTree.GetItemText(item)
1988        if name[:4] in dataTypes:
1989            names.append(name)
1990        item, cookie = G2frame.PatternTree.GetNextChild(G2frame.root, cookie)
1991    return names
1992                         
1993def GetPatternTreeItemId(G2frame, parentId, itemText):
1994    item, cookie = G2frame.PatternTree.GetFirstChild(parentId)
1995    while item:
1996        if G2frame.PatternTree.GetItemText(item) == itemText:
1997            return item
1998        item, cookie = G2frame.PatternTree.GetNextChild(parentId, cookie)
1999    return 0               
2000
2001def MovePatternTreeToGrid(G2frame,item):
2002   
2003#    print G2frame.PatternTree.GetItemText(item)
2004   
2005    oldPage = 0
2006    if G2frame.dataFrame:
2007        SetDataMenuBar(G2frame)
2008        if G2frame.dataFrame.GetLabel() == 'Comments':
2009            data = [G2frame.dataDisplay.GetValue()]
2010            G2frame.dataDisplay.Clear() 
2011            Id = GetPatternTreeItemId(G2frame,G2frame.root, 'Comments')
2012            if Id: G2frame.PatternTree.SetItemPyData(Id,data)
2013        elif G2frame.dataFrame.GetLabel() == 'Notebook':
2014            data = [G2frame.dataDisplay.GetValue()]
2015            G2frame.dataDisplay.Clear() 
2016            Id = GetPatternTreeItemId(G2frame,G2frame.root, 'Notebook')
2017            if Id: G2frame.PatternTree.SetItemPyData(Id,data)
2018        elif 'Phase Data for' in G2frame.dataFrame.GetLabel():
2019            if G2frame.dataDisplay: 
2020                oldPage = G2frame.dataDisplay.GetSelection()
2021        G2frame.dataFrame.Clear()
2022        G2frame.dataFrame.SetLabel('')
2023    else:
2024        #create the frame for the data item window
2025        G2frame.dataFrame = DataFrame(parent=G2frame.mainPanel,frame=G2frame)
2026
2027    G2frame.dataFrame.Raise()           
2028    G2frame.PickId = 0
2029    parentID = G2frame.root
2030    for i in G2frame.ExportPattern: i.Enable(False)
2031    defWid = [250,150]
2032    if item != G2frame.root:
2033        parentID = G2frame.PatternTree.GetItemParent(item)
2034    if G2frame.PatternTree.GetItemParent(item) == G2frame.root:
2035        G2frame.PatternId = item
2036        G2frame.PickId = item
2037        if G2frame.PatternTree.GetItemText(item) == 'Notebook':
2038            SetDataMenuBar(G2frame,G2frame.dataFrame.DataNotebookMenu)
2039            G2frame.PatternId = 0
2040            for i in G2frame.ExportPattern: i.Enable(False)
2041            data = G2frame.PatternTree.GetItemPyData(item)
2042            UpdateNotebook(G2frame,data)
2043        elif G2frame.PatternTree.GetItemText(item) == 'Controls':
2044            G2frame.PatternId = 0
2045            for i in G2frame.ExportPattern: i.Enable(False)
2046            data = G2frame.PatternTree.GetItemPyData(item)
2047            if not data:           #fill in defaults
2048                data = {
2049                    #least squares controls
2050                    'deriv type':'analytic Hessian','min dM/M':0.0001,'shift factor':1.0,'max cyc':3}
2051                G2frame.PatternTree.SetItemPyData(item,data)                             
2052            for i in G2frame.Refine: i.Enable(True)
2053            for i in G2frame.SeqRefine: i.Enable(True)
2054            UpdateControls(G2frame,data)
2055        elif G2frame.PatternTree.GetItemText(item) == 'Sequental results':
2056            data = G2frame.PatternTree.GetItemPyData(item)
2057            UpdateSeqResults(G2frame,data)           
2058        elif G2frame.PatternTree.GetItemText(item) == 'Covariance':
2059            data = G2frame.PatternTree.GetItemPyData(item)
2060            G2frame.dataFrame.setSizePosLeft(defWid)
2061            text = ''
2062            if 'Rvals' in data:
2063                Nvars = len(data['varyList'])
2064                Rvals = data['Rvals']
2065                text = '\nFinal residuals: \nRw = %.3f%% \nchi**2 = %.1f \nGOF = %.2f'%(Rvals['Rwp'],Rvals['chisq'],Rvals['GOF'])
2066                text += '\nNobs = %d \nNvals = %d'%(Rvals['Nobs'],Nvars)
2067                if 'lamMax' in Rvals:
2068                    text += '\nlog10 MaxLambda = %.1f'%(np.log10(Rvals['lamMax']))
2069            wx.TextCtrl(parent=G2frame.dataFrame,size=G2frame.dataFrame.GetClientSize(),
2070                value='See plot window for covariance display'+text,style=wx.TE_MULTILINE)
2071            G2plt.PlotCovariance(G2frame)
2072        elif G2frame.PatternTree.GetItemText(item) == 'Constraints':
2073            data = G2frame.PatternTree.GetItemPyData(item)
2074            G2cnstG.UpdateConstraints(G2frame,data)
2075        elif G2frame.PatternTree.GetItemText(item) == 'Rigid bodies':
2076            data = G2frame.PatternTree.GetItemPyData(item)
2077            G2cnstG.UpdateRigidBodies(G2frame,data)
2078        elif G2frame.PatternTree.GetItemText(item) == 'Restraints':
2079            data = G2frame.PatternTree.GetItemPyData(item)
2080            Phases = G2frame.GetPhaseData()
2081            phase = ''
2082            phaseName = ''
2083            if Phases:
2084                phaseName = Phases.keys()[0]
2085            G2frame.dataFrame.setSizePosLeft(defWid)
2086            G2restG.UpdateRestraints(G2frame,data,Phases,phaseName)
2087        elif 'IMG' in G2frame.PatternTree.GetItemText(item):
2088            G2frame.Image = item
2089            G2plt.PlotImage(G2frame,newPlot=True)
2090        elif 'PKS' in G2frame.PatternTree.GetItemText(item):
2091            G2plt.PlotPowderLines(G2frame)
2092        elif 'PWDR' in G2frame.PatternTree.GetItemText(item):
2093            for i in G2frame.ExportPattern: i.Enable(True)
2094            UpdatePWHKPlot(G2frame,'PWDR',item)
2095        elif 'HKLF' in G2frame.PatternTree.GetItemText(item):
2096            G2frame.Sngl = item
2097            UpdatePWHKPlot(G2frame,'HKLF',item)
2098        elif 'PDF' in G2frame.PatternTree.GetItemText(item):
2099            G2frame.PatternId = item
2100            for i in G2frame.ExportPDF: i.Enable(True)
2101            G2plt.PlotISFG(G2frame,type='S(Q)')
2102        elif G2frame.PatternTree.GetItemText(item) == 'Phases':
2103            G2frame.dataFrame.setSizePosLeft(defWid)
2104            wx.TextCtrl(parent=G2frame.dataFrame,size=G2frame.dataFrame.GetClientSize(),
2105                value='Select one phase to see its parameters')           
2106    elif 'I(Q)' in G2frame.PatternTree.GetItemText(item):
2107        G2frame.PickId = item
2108        G2frame.PatternId = G2frame.PatternTree.GetItemParent(item)
2109        G2plt.PlotISFG(G2frame,type='I(Q)',newPlot=True)
2110    elif 'S(Q)' in G2frame.PatternTree.GetItemText(item):
2111        G2frame.PickId = item
2112        G2frame.PatternId = G2frame.PatternTree.GetItemParent(item)
2113        G2plt.PlotISFG(G2frame,type='S(Q)',newPlot=True)
2114    elif 'F(Q)' in G2frame.PatternTree.GetItemText(item):
2115        G2frame.PickId = item
2116        G2frame.PatternId = G2frame.PatternTree.GetItemParent(item)
2117        G2plt.PlotISFG(G2frame,type='F(Q)',newPlot=True)
2118    elif 'G(R)' in G2frame.PatternTree.GetItemText(item):
2119        G2frame.PickId = item
2120        G2frame.PatternId = G2frame.PatternTree.GetItemParent(item)
2121        G2plt.PlotISFG(G2frame,type='G(R)',newPlot=True)           
2122    elif G2frame.PatternTree.GetItemText(parentID) == 'Phases':
2123        G2frame.PickId = item
2124        data = G2frame.PatternTree.GetItemPyData(item)
2125        G2phG.UpdatePhaseData(G2frame,item,data,oldPage)
2126    elif G2frame.PatternTree.GetItemText(item) == 'Comments':
2127        SetDataMenuBar(G2frame,G2frame.dataFrame.DataCommentsMenu)
2128        G2frame.PatternId = G2frame.PatternTree.GetItemParent(item)
2129        G2frame.PickId = item
2130        data = G2frame.PatternTree.GetItemPyData(item)
2131        UpdateComments(G2frame,data)
2132    elif G2frame.PatternTree.GetItemText(item) == 'Image Controls':
2133        G2frame.dataFrame.SetTitle('Image Controls')
2134        G2frame.PickId = item
2135        G2frame.Image = G2frame.PatternTree.GetItemParent(item)
2136        masks = G2frame.PatternTree.GetItemPyData(
2137            GetPatternTreeItemId(G2frame,G2frame.Image, 'Masks'))
2138        data = G2frame.PatternTree.GetItemPyData(item)
2139        G2imG.UpdateImageControls(G2frame,data,masks)
2140        G2plt.PlotImage(G2frame)
2141    elif G2frame.PatternTree.GetItemText(item) == 'Masks':
2142        G2frame.dataFrame.SetTitle('Masks')
2143        G2frame.PickId = item
2144        G2frame.Image = G2frame.PatternTree.GetItemParent(item)
2145        data = G2frame.PatternTree.GetItemPyData(item)
2146        G2imG.UpdateMasks(G2frame,data)
2147        G2plt.PlotImage(G2frame)
2148    elif G2frame.PatternTree.GetItemText(item) == 'Stress/Strain':
2149        G2frame.dataFrame.SetTitle('Stress/Strain')
2150        G2frame.PickId = item
2151        G2frame.Image = G2frame.PatternTree.GetItemParent(item)
2152        data = G2frame.PatternTree.GetItemPyData(item)
2153        G2imG.UpdateStressStrain(G2frame,data)
2154        G2plt.PlotImage(G2frame)
2155    elif G2frame.PatternTree.GetItemText(item) == 'HKL Plot Controls':
2156        G2frame.PickId = item
2157        G2frame.Sngl = G2frame.PatternTree.GetItemParent(item)
2158        data = G2frame.PatternTree.GetItemPyData(item)
2159        UpdateHKLControls(G2frame,data)
2160        G2plt.PlotSngl(G2frame)
2161    elif G2frame.PatternTree.GetItemText(item) == 'PDF Controls':
2162        G2frame.PatternId = G2frame.PatternTree.GetItemParent(item)
2163        for i in G2frame.ExportPDF: i.Enable(True)
2164        G2frame.PickId = item
2165        data = G2frame.PatternTree.GetItemPyData(item)
2166        G2pdG.UpdatePDFGrid(G2frame,data)
2167        G2plt.PlotISFG(G2frame,type='I(Q)')
2168        G2plt.PlotISFG(G2frame,type='S(Q)')
2169        G2plt.PlotISFG(G2frame,type='F(Q)')
2170        G2plt.PlotISFG(G2frame,type='G(R)')
2171    elif G2frame.PatternTree.GetItemText(item) == 'Peak List':
2172        G2frame.PatternId = G2frame.PatternTree.GetItemParent(item)
2173        for i in G2frame.ExportPeakList: i.Enable(True)
2174        G2frame.PickId = item
2175        data = G2frame.PatternTree.GetItemPyData(item)
2176        G2pdG.UpdatePeakGrid(G2frame,data)
2177        G2plt.PlotPatterns(G2frame)
2178    elif G2frame.PatternTree.GetItemText(item) == 'Background':
2179        G2frame.PatternId = G2frame.PatternTree.GetItemParent(item)
2180        G2frame.PickId = item
2181        data = G2frame.PatternTree.GetItemPyData(item)
2182        G2pdG.UpdateBackground(G2frame,data)
2183        G2plt.PlotPatterns(G2frame)
2184    elif G2frame.PatternTree.GetItemText(item) == 'Limits':
2185        G2frame.PatternId = G2frame.PatternTree.GetItemParent(item)
2186        G2frame.PickId = item
2187        data = G2frame.PatternTree.GetItemPyData(item)
2188        G2pdG.UpdateLimitsGrid(G2frame,data)
2189        G2plt.PlotPatterns(G2frame)
2190    elif G2frame.PatternTree.GetItemText(item) == 'Instrument Parameters':
2191        G2frame.PatternId = G2frame.PatternTree.GetItemParent(item)
2192        G2frame.PickId = item
2193        data = G2frame.PatternTree.GetItemPyData(item)[0]
2194        G2pdG.UpdateInstrumentGrid(G2frame,data)
2195        G2plt.PlotPeakWidths(G2frame)
2196    elif G2frame.PatternTree.GetItemText(item) == 'Sample Parameters':
2197        G2frame.PatternId = G2frame.PatternTree.GetItemParent(item)
2198        G2frame.PickId = item
2199        data = G2frame.PatternTree.GetItemPyData(item)
2200
2201        if 'Temperature' not in data:           #temp fix for old gpx files
2202            data = {'Scale':[1.0,True],'Type':'Debye-Scherrer','Absorption':[0.0,False],'DisplaceX':[0.0,False],
2203                'DisplaceY':[0.0,False],'Diffuse':[],'Temperature':300.,'Pressure':1.0,'Humidity':0.0,'Voltage':0.0,
2204                'Force':0.0,'Gonio. radius':200.0}
2205            G2frame.PatternTree.SetItemPyData(item,data)
2206   
2207        G2pdG.UpdateSampleGrid(G2frame,data)
2208        G2plt.PlotPatterns(G2frame)
2209    elif G2frame.PatternTree.GetItemText(item) == 'Index Peak List':
2210        G2frame.PatternId = G2frame.PatternTree.GetItemParent(item)
2211        for i in G2frame.ExportPeakList: i.Enable(True)
2212        G2frame.PickId = item
2213        data = G2frame.PatternTree.GetItemPyData(item)
2214        G2pdG.UpdateIndexPeaksGrid(G2frame,data)
2215        if 'PKS' in G2frame.PatternTree.GetItemText(G2frame.PatternId):
2216            G2plt.PlotPowderLines(G2frame)
2217        else:
2218            G2plt.PlotPatterns(G2frame)
2219    elif G2frame.PatternTree.GetItemText(item) == 'Unit Cells List':
2220        G2frame.PatternId = G2frame.PatternTree.GetItemParent(item)
2221        G2frame.PickId = item
2222        data = G2frame.PatternTree.GetItemPyData(item)
2223        if not data:
2224            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
2225            data.append([0,0,0,0,0,0,0,0,0,0,0,0,0,0])      #Bravais lattice flags
2226            data.append([])                                 #empty cell list
2227            data.append([])                                 #empty dmin
2228            G2frame.PatternTree.SetItemPyData(item,data)                             
2229        G2pdG.UpdateUnitCellsGrid(G2frame,data)
2230        if 'PKS' in G2frame.PatternTree.GetItemText(G2frame.PatternId):
2231            G2plt.PlotPowderLines(G2frame)
2232        else:
2233            G2plt.PlotPatterns(G2frame)
2234    elif G2frame.PatternTree.GetItemText(item) == 'Reflection Lists':   #powder reflections
2235        G2frame.PatternId = G2frame.PatternTree.GetItemParent(item)
2236        G2frame.PickId = item
2237        data = G2frame.PatternTree.GetItemPyData(item)
2238        G2frame.RefList = ''
2239        if len(data):
2240            G2frame.RefList = data.keys()[0]
2241        G2pdG.UpdateReflectionGrid(G2frame,data)
2242        G2plt.PlotPatterns(G2frame)
2243    elif G2frame.PatternTree.GetItemText(item) == 'Reflection List':    #HKLF reflections
2244        G2frame.PatternId = G2frame.PatternTree.GetItemParent(item)
2245        name = G2frame.PatternTree.GetItemText(G2frame.PatternId)
2246        data = G2frame.PatternTree.GetItemPyData(G2frame.PatternId)
2247        G2pdG.UpdateReflectionGrid(G2frame,data,HKLF=True,Name=name)
2248
2249def SetDataMenuBar(G2frame,menu=None):
2250        '''Set the menu for the data frame. On the Mac put this
2251        menu for the data tree window instead.
2252
2253        Note that data frame items do not have menus, for these (menu=None)
2254        display a blank menu or on the Mac display the standard menu for
2255        the data tree window.
2256        '''
2257        if sys.platform == "darwin":
2258            if menu is None:
2259                G2frame.SetMenuBar(G2frame.GSASIIMenu)
2260            else:
2261                G2frame.SetMenuBar(menu)
2262        else:
2263            if menu is None:
2264                G2frame.dataFrame.SetMenuBar(G2frame.dataFrame.BlankMenu)
2265            else:
2266                G2frame.dataFrame.SetMenuBar(menu)
Note: See TracBrowser for help on using the repository browser.