source: trunk/GSASII.py @ 19

Last change on this file since 19 was 19, checked in by vondreel, 13 years ago

image control fixups

File size: 78.9 KB
Line 
1#GSASII
2
3import os.path as ospath
4import sys
5import math
6import cPickle
7import time
8import numpy as np
9import wx
10import matplotlib as mpl
11# use the newer wxmpl when needed
12(main,sub) = mpl.__version__.split('.')[0:2]
13if int(main) > 0 or int(sub) > 91: 
14    import wxmpl131 as wxmpl
15else:
16    import wxmpl as wxmpl
17import pylab
18import GSASIIIO as G2IO
19import GSASIIcomp as G2cmp
20import GSASIIgrid as G2gd
21
22# print versions
23print "Available python module versions for pyGSASII:"
24print "python:     ",sys.version[:5]
25print "wxpython:   ",wx.__version__
26print "matplotlib: ",mpl.__version__
27print "numpy:      ",np.__version__
28print "wxmpl:      ",wxmpl.__version__
29
30__version__ = '0.1.2'
31
32# useful degree trig functions
33sind = lambda x: math.sin(x*math.pi/180.)
34cosd = lambda x: math.cos(x*math.pi/180.)
35tand = lambda x: math.tan(x*math.pi/180.)
36asind = lambda x: 180.*math.asin(x)/math.pi
37acosd = lambda x: 180.*math.acos(x)/math.pi
38atan2d = lambda x,y: 180.*math.atan2(y,x)/math.pi
39
40def create(parent):
41    return GSASII(parent)
42
43[wxID_GSASII, wxID_GSASIIPATTERNTREE, wxID_GSASIIDATA, wxID_GSASIIPICKGRID,
44] = [wx.NewId() for _init_ctrls in range(4)]
45
46[wxID_GSASIIFILECLOSE, wxID_GSASIIFILEEXIT, wxID_GSASIIFILEOPEN, 
47 wxID_GSASIIFILESAVE, wxID_GSASIIFILESAVEAS, wxID_GSASIIPEAKFIT, 
48 wxID_GSASIIINDEX, wxID_GSASIIAUTOPEAKFIT, wxID_GSASIIUNDO, wxID_GSASIIREFINECELL,
49] = [wx.NewId() for _init_coll_File_Items in range(10)]
50
51[wxID_GSASIIPWDRREAD,wxID_GSASIISNGLREAD,wxID_GSASIIADDPHASE,wxID_GSASIIDELETEPHASE,
52 wxID_GSASIIDATADELETE,wxID_GSASIIREADPEAKS,wxID_GSASIIPWDSUM,wxID_GSASIIIMGREAD,
53 wxID_GSASIIIMSUM,
54] = [wx.NewId() for _init_coll_Data_Items in range(9)]
55
56[wxID_GSASIIIMPORT, wxID_GSASIIIMPORTPATTERN, wxID_GSASIIIMPORTHKL, wxID_GSASIIIMPORTPHASE,
57wxID_GSASIIIMPORTCIF, wxID_GSASIIIMPORTPDB, 
58] = [wx.NewId() for _init_coll_Import_Items in range(6)]
59
60[wxID_GSAIIEXPORT, wxID_GSASIIEXPORTPATTERN, wxID_GSASIIEXPORTHKL, wxID_GSASIIEXPORTPHASE,
61wxID_GSASIIEXPORTCIF, wxID_GSASIIEXPORTPEAKLIST
62] = [wx.NewId() for _init_coll_Export_Items in range(6)]
63
64[wxID_GSASIIHELPABOUT, wxID_GSASIIHELPHELP, 
65] = [wx.NewId() for _init_coll_Help_Items in range(2)]
66
67class GSASII(wx.Frame):
68   
69    def _init_coll_GSASIIMenu_Menus(self, parent):
70        parent.Append(menu=self.File, title='File')
71        parent.Append(menu=self.Data, title='Data')
72        parent.Append(menu=self.Calculate, title='Calculate')
73        parent.Append(menu=self.Import, title='Import')
74        parent.Append(menu=self.Export, title='Export')
75        parent.Append(menu=self.Help, title='Help')
76
77    def _init_coll_File_Items(self, parent):
78        parent.Append(help='', id=wxID_GSASIIFILEOPEN, kind=wx.ITEM_NORMAL,
79            text='Open project')
80        parent.Append(help='', id=wxID_GSASIIFILESAVE, kind=wx.ITEM_NORMAL,
81            text='Save project')
82        parent.Append(help='', id=wxID_GSASIIFILESAVEAS, kind=wx.ITEM_NORMAL,
83            text='SaveAs')
84        parent.Append(help='', id=wxID_GSASIIFILECLOSE, kind=wx.ITEM_NORMAL,
85            text='Close project')
86        parent.Append(help='', id=wxID_GSASIIFILEEXIT, kind=wx.ITEM_NORMAL,
87            text='Exit')
88        self.Bind(wx.EVT_MENU, self.OnFileOpenMenu, id=wxID_GSASIIFILEOPEN)
89        self.Bind(wx.EVT_MENU, self.OnFileSaveMenu, id=wxID_GSASIIFILESAVE)
90        self.Bind(wx.EVT_MENU, self.OnFileSaveasMenu, id=wxID_GSASIIFILESAVEAS)
91        self.Bind(wx.EVT_MENU, self.OnFileCloseMenu, id=wxID_GSASIIFILECLOSE)
92        self.Bind(wx.EVT_MENU, self.OnFileExitMenu, id=wxID_GSASIIFILEEXIT)
93       
94    def _init_coll_Data_Items(self,parent):
95        parent.Append(help='', id=wxID_GSASIIPWDRREAD, kind=wx.ITEM_NORMAL,
96            text='Read powder data')
97        parent.Append(help='',id=wxID_GSASIIIMGREAD, kind=wx.ITEM_NORMAL,
98            text='Read image data')
99        parent.Append(help='',id=wxID_GSASIIREADPEAKS, kind=wx.ITEM_NORMAL,
100            text='Read Powder Pattern Peaks')
101        parent.Append(help='', id=wxID_GSASIISNGLREAD, kind=wx.ITEM_NORMAL,
102            text='Read single crystal data')
103        parent.Append(help='', id=wxID_GSASIIPWDSUM, kind=wx.ITEM_NORMAL,
104            text='Sum powder data')
105        parent.Append(help='',id=wxID_GSASIIIMSUM, kind=wx.ITEM_NORMAL,
106            text='Sum image data')
107        parent.Append(help='', id=wxID_GSASIIADDPHASE, kind=wx.ITEM_NORMAL,
108            text='Add phase')
109        parent.Append(help='', id=wxID_GSASIIDELETEPHASE, kind=wx.ITEM_NORMAL,
110            text='Delete phase')
111        parent.Append(help='', id=wxID_GSASIIDATADELETE, kind=wx.ITEM_NORMAL,
112            text='Delete data')
113        self.Bind(wx.EVT_MENU, self.OnPwdrReadMenu, id=wxID_GSASIIPWDRREAD)
114        self.Bind(wx.EVT_MENU, self.OnPwdrSumMenu, id=wxID_GSASIIPWDSUM)
115        self.Bind(wx.EVT_MENU, self.OnReadPowderPeaks, id=wxID_GSASIIREADPEAKS)
116        self.Bind(wx.EVT_MENU, self.OnImageRead, id=wxID_GSASIIIMGREAD)
117        self.Bind(wx.EVT_MENU, self.OnImageSum, id=wxID_GSASIIIMSUM)
118        self.Bind(wx.EVT_MENU, self.OnSnglReadMenu, id=wxID_GSASIISNGLREAD)
119        self.Bind(wx.EVT_MENU, self.OnAddPhase, id=wxID_GSASIIADDPHASE)
120        self.Bind(wx.EVT_MENU, self.OnDeletePhase, id=wxID_GSASIIDELETEPHASE)
121        self.Bind(wx.EVT_MENU, self.OnDataDeleteMenu, id=wxID_GSASIIDATADELETE)
122               
123    def _init_coll_Calculate_Items(self,parent):
124        self.UnDo = parent.Append(help='', id=wxID_GSASIIUNDO, kind=wx.ITEM_NORMAL,
125            text='UnDo')
126        self.PeakFit = parent.Append(help='', id=wxID_GSASIIPEAKFIT, kind=wx.ITEM_NORMAL,
127            text='PeakFit')
128        self.AutoPeakFit = parent.Append(help='', id=wxID_GSASIIAUTOPEAKFIT, kind=wx.ITEM_NORMAL,
129            text='AutoPeakFit')
130        self.RefineCell = parent.Append(help='', id=wxID_GSASIIREFINECELL, kind=wx.ITEM_NORMAL,
131            text='RefineCell')
132        self.IndexPeaks = parent.Append(help='', id=wxID_GSASIIINDEX, kind=wx.ITEM_NORMAL,
133            text='IndexPeaks')
134        self.UnDo.Enable(False)
135        self.PeakFit.Enable(False)
136        self.AutoPeakFit.Enable(False)
137        self.IndexPeaks.Enable(False)
138        self.RefineCell.Enable(False)
139        self.Bind(wx.EVT_MENU, self.OnUnDo, id=wxID_GSASIIUNDO)
140        self.Bind(wx.EVT_MENU, self.OnPeakFit, id=wxID_GSASIIPEAKFIT)
141        self.Bind(wx.EVT_MENU, self.OnAutoPeakFit, id=wxID_GSASIIAUTOPEAKFIT)
142        self.Bind(wx.EVT_MENU, self.OnRefineCell, id=wxID_GSASIIREFINECELL)
143        self.Bind(wx.EVT_MENU, self.OnIndexPeaks, id=wxID_GSASIIINDEX)
144       
145    def _init_coll_Import_Items(self,parent):
146        self.ImportPhase = parent.Append(help='Import phase data from GSAS EXP file',
147            id=wxID_GSASIIIMPORTPHASE, kind=wx.ITEM_NORMAL,text='Import GSAS EXP Phase')
148        self.ImportPDB = parent.Append(help='Import phase data from PDB file',
149            id=wxID_GSASIIIMPORTPDB, kind=wx.ITEM_NORMAL,text='Import PDB Phase')
150        self.ImportPattern = parent.Append(help='',id=wxID_GSASIIIMPORTPATTERN, kind=wx.ITEM_NORMAL,
151            text='Import Powder Pattern')
152        self.ImportHKL = parent.Append(help='',id=wxID_GSASIIIMPORTHKL, kind=wx.ITEM_NORMAL,
153            text='Import HKLs')
154        self.ImportCIF = parent.Append(help='',id=wxID_GSASIIIMPORTCIF, kind=wx.ITEM_NORMAL,
155            text='Import CIF')
156        self.Bind(wx.EVT_MENU, self.OnImportPhase, id=wxID_GSASIIIMPORTPHASE)
157        self.Bind(wx.EVT_MENU, self.OnImportPDB, id=wxID_GSASIIIMPORTPDB)
158        self.Bind(wx.EVT_MENU, self.OnImportPattern, id=wxID_GSASIIIMPORTPATTERN)
159        self.Bind(wx.EVT_MENU, self.OnImportHKL, id=wxID_GSASIIIMPORTHKL)
160        self.Bind(wx.EVT_MENU, self.OnImportCIF, id=wxID_GSASIIIMPORTCIF)
161
162    def _init_coll_Export_Items(self,parent):
163        self.ExportPattern = parent.Append(help='',id=wxID_GSASIIEXPORTPATTERN, kind=wx.ITEM_NORMAL,
164            text='Export Powder Pattern')
165        self.ExportPeakList = parent.Append(help='',id=wxID_GSASIIEXPORTPEAKLIST, kind=wx.ITEM_NORMAL,
166            text='Export All Peak Lists')
167        self.ExportHKL = parent.Append(help='',id=wxID_GSASIIEXPORTHKL, kind=wx.ITEM_NORMAL,
168            text='Export HKLs')
169        self.ExportPhase = parent.Append(help='',id=wxID_GSASIIEXPORTPHASE, kind=wx.ITEM_NORMAL,
170            text='Export Phase')
171        self.ExportCIF = parent.Append(help='',id=wxID_GSASIIEXPORTCIF, kind=wx.ITEM_NORMAL,
172            text='Export CIF')
173        self.ExportPattern.Enable(False)
174        self.ExportPeakList.Enable(True)
175        self.ExportHKL.Enable(False)
176        self.ExportPhase.Enable(False)
177        self.ExportCIF.Enable(False)
178        self.Bind(wx.EVT_MENU, self.OnExportPattern, id=wxID_GSASIIEXPORTPATTERN)
179        self.Bind(wx.EVT_MENU, self.OnExportPeakList, id=wxID_GSASIIEXPORTPEAKLIST)
180        self.Bind(wx.EVT_MENU, self.OnExportHKL, id=wxID_GSASIIEXPORTHKL)
181        self.Bind(wx.EVT_MENU, self.OnExportPhase, id=wxID_GSASIIEXPORTPHASE)
182        self.Bind(wx.EVT_MENU, self.OnExportCIF, id=wxID_GSASIIEXPORTCIF)
183               
184    def _init_coll_Help_Items(self, parent):
185        parent.Append(help='', id=wxID_GSASIIHELPHELP, kind=wx.ITEM_NORMAL,
186            text='Help')
187        parent.Append(help='', id=wxID_GSASIIHELPABOUT, kind=wx.ITEM_NORMAL,
188            text='About')
189        self.Bind(wx.EVT_MENU, self.OnHelpHelpMenu, id=wxID_GSASIIHELPHELP)
190        self.Bind(wx.EVT_MENU, self.OnHelpAboutMenu, id=wxID_GSASIIHELPABOUT)
191
192    def _init_utils(self):
193        self.GSASIIMenu = wx.MenuBar()
194        self.File = wx.Menu(title='')
195        self.Data = wx.Menu(title='')       
196        self.Calculate = wx.Menu(title='')       
197        self.Import = wx.Menu(title='')       
198        self.Export = wx.Menu(title='')       
199        self.Help = wx.Menu(title='')
200
201        self._init_coll_GSASIIMenu_Menus(self.GSASIIMenu)
202        self._init_coll_File_Items(self.File)
203        self._init_coll_Data_Items(self.Data)
204        self._init_coll_Calculate_Items(self.Calculate)
205        self._init_coll_Import_Items(self.Import)
206        self._init_coll_Export_Items(self.Export)
207        self._init_coll_Help_Items(self.Help)
208       
209    def _init_ctrls(self, parent):
210        wx.Frame.__init__(self, id=wxID_GSASII, name='GSASII', parent=parent,
211            size=wx.Size(300, 250),style=wx.DEFAULT_FRAME_STYLE, title='GSAS-II')
212        screenSize = wx.DisplaySize()
213        Size = self.GetSize()
214        xPos = screenSize[0]-Size[0]
215        self.SetPosition(wx.Point(xPos,0))
216        self._init_utils()
217        self.SetMenuBar(self.GSASIIMenu)
218        self.Bind(wx.EVT_SIZE, self.OnSize)
219        self.mainPanel = wx.Panel(self,-1)
220       
221        self.PatternTree = wx.TreeCtrl(id=wxID_GSASIIPATTERNTREE,
222            parent=self.mainPanel, pos=wx.Point(0, 0),style=wx.TR_DEFAULT_STYLE )
223        self.PatternTree.Bind(wx.EVT_TREE_SEL_CHANGED,
224            self.OnPatternTreeSelChanged, id=wxID_GSASIIPATTERNTREE)
225        self.PatternTree.Bind(wx.EVT_TREE_ITEM_COLLAPSED,
226            self.OnPatternTreeItemCollapsed, id=wxID_GSASIIPATTERNTREE)
227        self.PatternTree.Bind(wx.EVT_TREE_ITEM_EXPANDED,
228            self.OnPatternTreeItemExpanded, id=wxID_GSASIIPATTERNTREE)
229        self.root = self.PatternTree.AddRoot("Loaded Data")
230       
231        self.dataDisplay = None
232       
233    def __init__(self, parent):
234        self._init_ctrls(parent)
235        self.Bind(wx.EVT_CLOSE, self.ExitMain)
236        self.dirname = ''
237        self.GSASprojectfile = ''
238        self.Offset = 0.0
239        self.Weight = False
240        self.IparmName = ''
241        self.NewPlot = True
242        self.IfPlot = False
243        self.PatternId = 0
244        self.PickId = 0
245        self.PeakTable = []
246        self.LimitsTable = []
247        self.HKL = []
248        self.Lines = []
249        self.itemPicked = None
250        self.dataFrame = None
251        self.Contour = False
252        self.plotView = 0
253        self.Image = 0
254        self.Img = 0
255        self.imageDefault = {}
256
257    def OnSize(self,event):
258        w,h = self.GetClientSizeTuple()
259        self.mainPanel.SetSize(wx.Size(w,h))
260        self.PatternTree.SetSize(wx.Size(w,h))
261                       
262    def OnPatternTreeSelChanged(self, event):
263        if self.PickId:
264            if self.PatternTree.GetItemText(self.PickId) in ['Peak List','Limits','Peak Index List','Unit Cell List','Background']:
265                ax = self.pdplot.gca()
266                self.plotView = [ax.get_xlim(),ax.get_ylim()]
267        item = event.GetItem()
268        G2gd.MovePatternTreeToGrid(self,item)
269       
270    def OnPatternTreeItemCollapsed(self, event):
271        event.Skip()
272
273    def OnPatternTreeItemExpanded(self, event):
274        self.PatternTree.ScrollTo(self.PatternTree.GetLastChild(event.GetItem()))
275       
276    def OnPatternTreeDeleteItem(self, event):
277        event.Skip()
278
279    def OnPatternTreeItemActivated(self, event):
280        event.Skip()
281       
282    def OnPwdrReadMenu(self, event):
283        if not G2gd.GetPatternTreeItemId(self,self.root,'Notebook'):
284            sub = self.PatternTree.AppendItem(parent=self.root,text='Notebook')
285            self.PatternTree.SetItemPyData(sub,[''])
286            sub = self.PatternTree.AppendItem(parent=self.root,text='Controls')
287            self.PatternTree.SetItemPyData(sub,[0])
288        dlg = wx.FileDialog(self, 'Choose files', '.', '', 
289            'GSAS fxye files (*.fxye)|*.fxye|GSAS fxy files (*.fxy)|*.fxy|All files (*.*)|*.*', 
290            wx.OPEN | wx.MULTIPLE)
291        if self.dirname: dlg.SetDirectory(self.dirname)
292        try:
293            if dlg.ShowModal() == wx.ID_OK:
294                filenames = dlg.GetPaths()
295                filenames.sort()
296                self.dirname = dlg.GetDirectory()
297                for filename in filenames:
298                    Data,Iparm,Comments = G2IO.SelectPowderData(self, filename)              #Data: list of tuples (filename,Pos,Bank)
299                    if not Data:                                                    #if Data rejected by user - go to next one
300                        continue
301                    DataType = Iparm['INS   HTYPE ']                                #expect only 4 char string
302                    DataType = DataType.strip()[0:3]                                #just 1st 3 chars
303                    wx.BeginBusyCursor()
304                    try:
305                        for Item in Data:
306                            vals = Item[2].split()          #split up the BANK record
307                            Id = self.PatternTree.AppendItem(parent=self.root,text='PWDR '+ospath.basename(Item[0])+': '+vals[0]+vals[1])
308                            data = G2IO.GetPowderData(filename,Item[1],Item[2],DataType)
309                            self.PatternTree.SetItemPyData(Id,[Item,data])
310                            '''
311                            Each tree item data is a list with:
312                            Item: the (filename,Pos,Bank) tuple
313                            data: (x,y,w,yc,yb,yd) list from GetPowderData
314                            '''
315                           
316                            self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Comments'),Comments)                           
317                            Tmin = min(data[0])
318                            Tmax = max(data[0])
319                            self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Limits'),[(Tmin,Tmax),[Tmin,Tmax]])
320                            self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Background'),[['chebyschev',1,3,1.0,0.0,0.0]])
321       
322                            data = [DataType,]
323                            if 'C' in DataType:
324                                s = Iparm['INS  1 ICONS']
325                                v = (G2IO.sfloat(s[:10]),G2IO.sfloat(s[10:20]),G2IO.sfloat(s[20:30]),G2IO.sfloat(s[55:65]),G2IO.sfloat(s[40:50])) #get lam1, lam2, zero, pola & ratio
326                                if not v[1]:
327                                    names = ['Type','Lam','Zero','Polariz.','U','V','W','X','Y','SH/L'] 
328                                    v = (v[0],v[2],v[4])
329                                    codes = [0,0,0,0]
330                                else:
331                                    names = ['Type','Lam1','Lam2','Zero','I(L2)/I(L1)','Polariz.','U','V','W','X','Y','SH/L']
332                                    codes = [0,0,0,0,0,0]
333                                data.extend(v)
334                                v1 = Iparm['INS  1PRCF1 '].split()                                                 
335                                v = Iparm['INS  1PRCF11'].split()
336                                data.extend([float(v[0]),float(v[1]),float(v[2])])                  #get GU, GV & GW - always here
337                                v = Iparm['INS  1PRCF12'].split()
338                                if v1[0] == 3:
339                                    data.extend([float(v[0]),float(v[1]),float(v[2])+float(v[3])])  #get LX, LY & S+H/L
340                                else:
341                                    data.extend([0.0,0.0,0.002])                                      #OK defaults if fxn #3 not 1st in iprm file
342                                codes.extend([0,0,0,0,0,0])
343                            self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Instrument Parameters'),[tuple(data),data,codes,names])
344                            self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Peak List'),[])
345                            self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Index Peak List'),[])
346                            self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Unit Cells List'),[])             
347                            self.PatternId = G2gd.GetPatternTreeItemId(self,Id,'Limits')
348                    finally:
349                        wx.EndBusyCursor()
350                self.NewPlot = True
351                self.PlotPatterns()
352   
353        finally:
354            dlg.Destroy()
355        self.PatternTree.Expand(self.root)
356       
357    def OnReadPowderPeaks(self,event):
358        Cuka = 1.54052
359        if not G2gd.GetPatternTreeItemId(self,self.root,'Notebook'):
360            sub = self.PatternTree.AppendItem(parent=self.root,text='Notebook')
361            self.PatternTree.SetItemPyData(sub,[''])
362        dlg = wx.FileDialog(self, 'Choose file with peak list', '.', '', 
363            'peak files (*.txt)|*.txt|All files (*.*)|*.*',wx.OPEN)
364        if self.dirname:
365            dlg.SetDirectory(self.dirname)
366        try:
367            if dlg.ShowModal() == wx.ID_OK:
368                self.HKL = []
369                self.powderfile = dlg.GetPath()
370                self.dirname = dlg.GetDirectory()
371                comments,peaks = G2IO.GetPowderPeaks(self.powderfile)
372                Id = self.PatternTree.AppendItem(parent=self.root,text='PKS '+ospath.basename(self.powderfile))
373                data = ['PKS',Cuka,0.0]
374                names = ['Type','Lam','Zero'] 
375                codes = [0,0]
376                self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Instrument Parameters'),[tuple(data),data,codes,names])
377                self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Comments'),comments)
378                self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Index Peak List'),peaks)
379                self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Unit Cells List'),[])             
380                self.NewPlot = True
381        finally:
382            dlg.Destroy()
383           
384    def OnImageRead(self,event):
385        import copy
386        if not G2gd.GetPatternTreeItemId(self,self.root,'Notebook'):
387            sub = self.PatternTree.AppendItem(parent=self.root,text='Notebook')
388            self.PatternTree.SetItemPyData(sub,[''])
389        dlg = wx.FileDialog(self, 'Choose image file', '.', '', \
390            'MAR345 (*.mar3450)|*.mar3450|ADSC Image (*.img)|*.img|Perkin-Elmer TIF (*.tif)|*.tif|All files (*.*)|*.*',wx.OPEN)
391        if self.dirname:
392            dlg.SetDirectory(self.dirname)
393        try:
394            if dlg.ShowModal() == wx.ID_OK:
395                self.imagefile = dlg.GetPath()
396                self.dirname = dlg.GetDirectory()
397                ext = ospath.splitext(self.imagefile)[1]
398                Comments = []
399                if ext == '.tif':
400                    Comments,Data,Size,Image = G2IO.GetTifData(self.imagefile)
401                elif ext == '.img':
402                    Comments,Data,Size,Image = G2IO.GetImgData(self.imagefile)
403                    Image[0][0] = 0
404                elif ext == '.mar3450':
405                    Comments,Data,Size,Image = G2IO.GetMAR345Data(self.imagefile)
406                if Comments:
407                    Id = self.PatternTree.AppendItem(parent=self.root,text='IMG '+ospath.basename(self.imagefile))
408                    self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Comments'),Comments)
409                    Imax = np.amax(Image)
410                    Imin = np.amin(Image)
411                    if self.imageDefault:
412                        Data = copy.copy(self.imageDefault)
413                    else:
414                        Data['color'] = 'binary'
415                        Data['tilt'] = 0.0
416                        Data['rotation'] = 0.0
417                        Data['refine'] = [True,False,True,True,True]
418                        Data['showLines'] = False
419                        Data['ring'] = []
420                        Data['masks'] = []
421                        Data['calibrant'] = ''
422                        Data['IOradii'] = [10.,100.]
423                        Data['LRazimuth'] = [-45,45]
424                        Data['outChannels'] = 2500
425                    Data['setDefault'] = False
426                    Data['range'] = [(Imin,Imax),[Imin,Imax]]
427                    self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Image Controls'),Data)
428                    self.PatternTree.SetItemPyData(Id,[Size,Image])
429                    self.PickId = Id
430                    self.Image = Id
431                    self.PlotImage()
432        finally:
433            dlg.Destroy()       
434       
435    def OnSnglReadMenu(self,event):
436        if not G2gd.GetPatternTreeItemId(self,self.root,'Notebook'):
437            self.PatternTree.AppendItem(parent=self.root,text='')
438            self.PatternTree.AppendItem(parent=self.root,text='Controls')
439        dlg = wx.FileDialog(self, 'Choose file', '.', '', 
440            'hkl files (*.hkl)|*.hkl|All files (*.*)|*.*', 
441            wx.OPEN)
442        if self.dirname: dlg.SetDirectory(self.dirname)
443        try:
444            if dlg.ShowModal() == wx.ID_OK:
445                filename = dlg.GetPath()
446                self.dirname = dlg.GetDirectory()
447                wx.BeginBusyCursor()
448                try:
449                    names = ['Type','Lam']
450                    HKLref = G2IO.GetHKLData(filename)
451                    Id = self.PatternTree.AppendItem(parentId=self.root,text='SXTL '+ospath.basename(filename))
452                    self.PatternTree.SetItemPyData(Id,[filename,HKLref])
453                    Sub = self.PatternTree.AppendItem(Id,text='Instrument Parameters')
454                    data = ['SXC',1.5428,]
455                    self.PatternTree.SetItemPyData(Sub,[tuple(data),data,names])
456                finally:
457                    wx.EndBusyCursor()   
458        finally:
459            dlg.Destroy()
460        self.PatternTree.Expand(self.root)
461       
462    class SumDialog(wx.Dialog):
463        def __init__(self,parent,title,text,type,data):
464            wx.Dialog.__init__(self,parent,-1,title, 
465                pos=wx.DefaultPosition,style=wx.DEFAULT_DIALOG_STYLE)
466            self.data = data
467            panel = wx.Panel(self)
468            mainSizer = wx.BoxSizer(wx.VERTICAL)
469            topLabl = wx.StaticText(panel,-1,text)
470            mainSizer.Add((10,10),1)
471            mainSizer.Add(topLabl,0,wx.ALIGN_CENTER_VERTICAL|wx.LEFT,10)
472            mainSizer.Add((10,10),1)
473            dataGridSizer = wx.FlexGridSizer(rows=len(data),cols=2,hgap=2,vgap=2)
474            for id,item in enumerate(self.data[:-1]):
475                name = wx.TextCtrl(panel,-1,item[1],size=wx.Size(200,20))
476                name.SetEditable(False)
477                scale = wx.TextCtrl(panel,id,str(item[0]),style=wx.TE_PROCESS_ENTER)
478                scale.Bind(wx.EVT_TEXT,self.OnScaleChange)                   
479                dataGridSizer.Add(scale,0,wx.LEFT,10)
480                dataGridSizer.Add(name,0,wx.RIGHT,10)
481            dataGridSizer.Add(wx.StaticText(panel,-1,'Sum result name: '+type),0, \
482                wx.LEFT|wx.TOP|wx.ALIGN_CENTER_VERTICAL,10)
483            self.name = wx.TextCtrl(panel,-1,self.data[-1],size=wx.Size(200,20),style=wx.TE_PROCESS_ENTER)
484            self.name.Bind(wx.EVT_TEXT,self.OnNameChange)
485            dataGridSizer.Add(self.name,0,wx.RIGHT|wx.TOP,10)
486            mainSizer.Add(dataGridSizer,0,wx.EXPAND)
487            OkBtn = wx.Button(panel,-1,"Ok")
488            OkBtn.Bind(wx.EVT_BUTTON, self.OnOk)
489            cancelBtn = wx.Button(panel,-1,"Cancel")
490            cancelBtn.Bind(wx.EVT_BUTTON, self.OnCancel)
491            btnSizer = wx.BoxSizer(wx.HORIZONTAL)
492            btnSizer.Add((20,20),1)
493            btnSizer.Add(OkBtn)
494            btnSizer.Add((20,20),1)
495            btnSizer.Add(cancelBtn)
496            btnSizer.Add((20,20),1)
497           
498            mainSizer.Add(btnSizer,0,wx.EXPAND|wx.BOTTOM|wx.TOP, 10)
499            panel.SetSizer(mainSizer)
500            panel.Fit()
501            self.Fit()
502           
503        def OnNameChange(self,event):
504            self.data[-1] = self.name.GetValue() 
505           
506        def OnScaleChange(self,event):
507            id = event.GetId()
508            value = self.FindWindowById(id).GetValue()
509            try:
510                self.data[id][0] = float(value)
511            except ValueError:
512                if value and '-' not in value[0]:
513                    print 'bad input - numbers only'
514                    self.FindWindowById(id).SetValue('0.0')
515           
516        def OnOk(self,event):
517            parent = self.GetParent()
518            parent.Raise()
519            self.SetReturnCode(wx.ID_OK)
520            self.MakeModal(False)             
521            self.Destroy()
522           
523        def OnCancel(self,event):
524            parent = self.GetParent()
525            parent.Raise()
526            self.SetReturnCode(wx.ID_CANCEL)
527            self.MakeModal(False)             
528            self.Destroy()
529           
530        def GetData(self):
531                return self.data
532           
533    def OnPwdrSumMenu(self,event):
534        TextList = []
535        DataList = []
536        SumList = []
537        Names = []
538        Inst = []
539        SumItemList = []
540        Comments = ['Sum equals: \n']
541        if self.PatternTree.GetCount():
542            item, cookie = self.PatternTree.GetFirstChild(self.root)
543            while item:
544                name = self.PatternTree.GetItemText(item)
545                Names.append(name)
546                if 'PWDR' in name:
547                    TextList.append([0.0,name])
548                    DataList.append(self.PatternTree.GetItemPyData(item)[1])    # (x,y,w,yc,yb,yd)
549                    if not Inst:
550                        Inst = self.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(self,item, 'Instrument Parameters'))
551                item, cookie = self.PatternTree.GetNextChild(self.root, cookie)
552            if len(TextList) < 2:
553                self.ErrorDialog('Not enough data to sum','There must be more than one "PWDR" pattern')
554                return
555            TextList.append('default sum name')               
556            dlg = self.SumDialog(self,'Sum data','Enter scale for each pattern in summation','PWDR',TextList)
557            try:
558                if dlg.ShowModal() == wx.ID_OK:
559                    lenX = 0
560                    Xminmax = [0,0]
561                    Xsum = []
562                    Ysum = []
563                    Wsum = []
564                    result = dlg.GetData()
565                    for i,item in enumerate(result[:-1]):
566                        scale,name = item
567                        data = DataList[i]
568                        if scale:
569                            Comments.append("%10.3f %s" % (scale,' * '+name))
570                            x,y,w,yc,yb,yd = data
571                            if lenX:
572                                if lenX != len(x):
573                                    self.ErrorDialog('Data length error','Data to be summed must have same number of points'+ \
574                                        '\nExpected:'+str(lenX)+ \
575                                        '\nFound:   '+str(len(x))+'\nfor '+name)
576                                    return
577                            else:
578                                lenX = len(x)
579                            if Xminmax[1]:
580                                if Xminmax != [x[0],x[-1]]:
581                                    self.ErrorDialog('Data range error','Data to be summed must span same range'+ \
582                                        '\nExpected:'+str(Xminmax[0])+' '+str(Xminmax[1])+ \
583                                        '\nFound:   '+str(x[0])+' '+str(x[-1])+'\nfor '+name)
584                                    return
585                                else:
586                                    for j,yi in enumerate(y):
587                                         Ysum[j] += scale*yi
588                            else:
589                                Xminmax = [x[0],x[-1]]
590                                YCsum = [0.0 for i in range(lenX)]
591                                YBsum = [0.0 for i in range(lenX)]
592                                YDsum = [0.0 for i in range(lenX)]
593                                for j,yi in enumerate(y):
594                                    Xsum.append(x[j])
595                                    Ysum.append(scale*yi)
596                                    Wsum.append(w[j])
597                    outname = 'PWDR '+result[-1]
598                    Id = 0
599                    if outname in Names:
600                        dlg2 = wx.MessageDialog(self,'Overwrite data?','Duplicate data name',wx.OK|wx.CANCEL)
601                        try:
602                            if dlg2.ShowModal() == wx.ID_OK:
603                                Id = G2gd.GetPatternTreeItemId(self,self.root,name)
604                        finally:
605                            dlg2.Destroy()
606                    else:
607                        Id = self.PatternTree.AppendItem(parent=self.root,text=outname)
608                    if Id:
609                        self.PatternTree.SetItemPyData(Id,[[''],[Xsum,Ysum,Wsum,YCsum,YBsum,YDsum]])
610                        self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Comments'),Comments)                   
611                        self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Limits'),[tuple(Xminmax),Xminmax])
612                        self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Background'),[['chebyschev',1,3,1.0,0.0,0.0]])
613                        self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Instrument Parameters'),Inst)
614                        self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Peak List'),[])
615                        self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Index Peak List'),[])
616                        self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Unit Cells List'),[])             
617                   
618                    self.PlotPatterns()
619                    self.NewPlot = True
620            finally:
621                dlg.Destroy()
622
623    def OnImageSum(self,event):
624        TextList = []
625        DataList = []
626        SumList = []
627        Names = []
628        Inst = []
629        SumItemList = []
630        Comments = ['Sum equals: \n']
631        if self.PatternTree.GetCount():
632            item, cookie = self.PatternTree.GetFirstChild(self.root)
633            while item:
634                name = self.PatternTree.GetItemText(item)
635                Names.append(name)
636                if 'IMG' in name:
637                    TextList.append([0.0,name])
638                    DataList.append(self.PatternTree.GetItemPyData(item))        #Size,Image
639                    Data = self.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(self,item,'Image Controls'))
640                item, cookie = self.PatternTree.GetNextChild(self.root, cookie)
641            if len(TextList) < 2:
642                self.ErrorDialog('Not enough data to sum','There must be more than one "IMG" pattern')
643                return
644            TextList.append('default sum name')               
645            dlg = self.SumDialog(self,'Sum data','Enter scale for each image in summation','IMG',TextList)
646            try:
647                if dlg.ShowModal() == wx.ID_OK:
648                    imSize = 0
649                    newImage = []
650                    result = dlg.GetData()
651                    for i,item in enumerate(result[:-1]):
652                        scale,name = item
653                        data = DataList[i]
654                        if scale:
655                            Comments.append("%10.3f %s" % (scale,' * '+name))
656                            size,image = data
657                            if imSize:
658                                if imSize != size:
659                                    self.ErrorDialog('Image size error','Images to be summed must be same size'+ \
660                                        '\nExpected:'+str(imSize)+ \
661                                        '\nFound:   '+str(size)+'\nfor '+name)
662                                    return
663                                newImage += scale*image
664                            else:
665                                imSize = size
666                                newImage = scale*image
667                    outname = 'IMG '+result[-1]
668                    Id = 0
669                    if outname in Names:
670                        dlg2 = wx.MessageDialog(self,'Overwrite data?','Duplicate data name',wx.OK|wx.CANCEL)
671                        try:
672                            if dlg2.ShowModal() == wx.ID_OK:
673                                Id = G2gd.GetPatternTreeItemId(self,self.root,name)
674                        finally:
675                            dlg2.Destroy()
676                    else:
677                        Id = self.PatternTree.AppendItem(parent=self.root,text=outname)
678                    if Id:
679                        self.PatternTree.SetItemPyData(Id,[imSize,newImage])
680                        self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Comments'),Comments)
681                        self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Image Controls'),Data)                                           
682                    self.PickId = Id
683                    self.Image = Id
684                    self.PlotImage()
685                    self.NewPlot = True
686            finally:
687                dlg.Destroy()
688                     
689    def OnAddPhase(self,event):
690        if not G2gd.GetPatternTreeItemId(self,self.root,'Phases'):
691            sub = self.PatternTree.AppendItem(parent=self.root,text='Phases')
692        else:
693            sub = G2gd.GetPatternTreeItemId(self,self.root,'Phases')
694        PhaseName = ''
695        dlg = wx.TextEntryDialog(None,'Enter a name for this phase','Phase Name Entry','New phase',
696            style=wx.OK)
697        if dlg.ShowModal() == wx.ID_OK:
698            PhaseName = dlg.GetValue()
699        dlg.Destroy()
700        sub = self.PatternTree.AppendItem(parent=sub,text=PhaseName)
701        SGData = {'SpGrp':'P 1'}
702        self.PatternTree.SetItemPyData(sub, \
703            {'General':[PhaseName,'nuclear',SGData,[False,10.,10.,10.,90.,90.,90,1000.],
704            [False,1.0],[],{},[],[],[]],'Atoms':[]})
705       
706    def OnDeletePhase(self,event):
707        if self.dataFrame:
708            self.dataFrame.Clear() 
709        TextList = []
710        DelList = []
711        DelItemList = []
712        if G2gd.GetPatternTreeItemId(self,self.root,'Phases'):
713            sub = G2gd.GetPatternTreeItemId(self,self.root,'Phases')
714        else:
715            return
716        if sub:
717            item, cookie = self.PatternTree.GetFirstChild(sub)
718            while item:
719                TextList.append(self.PatternTree.GetItemText(item))
720                item, cookie = self.PatternTree.GetNextChild(sub, cookie)               
721            dlg = wx.MultiChoiceDialog(self, 'Which phase to delete?', 'Delete phase', TextList, wx.CHOICEDLG_STYLE)
722            try:
723                if dlg.ShowModal() == wx.ID_OK:
724                    result = dlg.GetSelections()
725                    for i in result: DelList.append([i,TextList[i]])
726                    item, cookie = self.PatternTree.GetFirstChild(sub)
727                    i = 0
728                    while item:
729                        if [i,self.PatternTree.GetItemText(item)] in DelList: DelItemList.append(item)
730                        item, cookie = self.PatternTree.GetNextChild(sub, cookie)
731                        i += 1
732                    for item in DelItemList:
733                        self.PatternTree.Delete(item)
734            finally:
735                dlg.Destroy()       
736       
737    def OnDataDeleteMenu(self, event):
738        TextList = []
739        DelList = []
740        DelItemList = []
741        if self.PatternTree.GetCount():
742            item, cookie = self.PatternTree.GetFirstChild(self.root)
743            while item:
744                name = self.PatternTree.GetItemText(item)
745                if 'PWDR' in name or 'SXTL' in name or 'IMG' in name:
746                    TextList.append(name)
747                item, cookie = self.PatternTree.GetNextChild(self.root, cookie)               
748            dlg = wx.MultiChoiceDialog(self, 'Which data to delete?', 'Delete data', TextList, wx.CHOICEDLG_STYLE)
749            try:
750                if dlg.ShowModal() == wx.ID_OK:
751                    result = dlg.GetSelections()
752                    for i in result: DelList.append(TextList[i])
753                    item, cookie = self.PatternTree.GetFirstChild(self.root)
754                    while item:
755                        if self.PatternTree.GetItemText(item) in DelList: DelItemList.append(item)
756                        item, cookie = self.PatternTree.GetNextChild(self.root, cookie)
757                    for item in DelItemList:
758                        self.PatternTree.Delete(item)
759                    self.PlotPatterns()
760                    self.NewPlot = True
761            finally:
762                dlg.Destroy()
763
764    def OnFileOpenMenu(self, event):
765        result = ''
766        if self.PatternTree.GetChildrenCount(self.root,False):
767            if self.dataFrame:
768                self.dataFrame.Clear() 
769            dlg = wx.MessageDialog(self, 'Overwrite?','Project exists!',  wx.OK | wx.CANCEL)
770            try:
771                result = dlg.ShowModal()
772                if result == wx.ID_OK:
773                    self.PatternTree.DeleteChildren(self.root)
774            finally:
775                dlg.Destroy()
776        if result != wx.ID_CANCEL:   
777            if self.dataDisplay: self.dataDisplay.Destroy()
778            dlg = wx.FileDialog(self, 'Choose GSAS-II project file', '.', '', 
779                'GSAS-II project file (*.gpx)|*.gpx',wx.OPEN)
780            if self.dirname: dlg.SetDirectory(self.dirname)
781            try:
782                if dlg.ShowModal() == wx.ID_OK:
783                    self.GSASprojectfile = dlg.GetPath()
784                    self.dirname = dlg.GetDirectory()
785                    G2IO.ProjFileOpen(self)
786                    self.HKL = []
787                    self.NewPlot = True
788#                    self.PlotPatterns()
789            finally:
790                dlg.Destroy()
791
792    def OnFileCloseMenu(self, event):
793        if self.dataFrame:
794            self.dataFrame.Clear()
795            self.dataFrame.SetLabel('GSAS-II data display') 
796        dlg = wx.MessageDialog(self, 'Save current project?', ' ', wx.YES | wx.NO | wx.CANCEL)
797        try:
798            result = dlg.ShowModal()
799            if result == wx.ID_OK:
800                self.OnFileSaveMenu(event)
801            if result != wx.ID_CANCEL:
802                self.GSASprojectfile = ''
803                self.PatternTree.DeleteChildren(self.root)
804                if self.HKL: self.HKL = []
805                self.NewPlot = True
806                self.PlotPatterns()
807        finally:
808            dlg.Destroy()
809
810    def OnFileSaveMenu(self, event):
811        if self.GSASprojectfile: 
812            G2IO.ProjFileSave(self)
813        else:
814            self.OnFileSaveasMenu(event)
815
816    def OnFileSaveasMenu(self, event):
817        dlg = wx.FileDialog(self, 'Choose GSAS-II project file name', '.', '', 
818            'GSAS-II project file (*.gpx)|*.gpx',wx.FD_SAVE|wx.FD_OVERWRITE_PROMPT)
819        if self.dirname:
820            dlg.SetDirectory(self.dirname)
821        try:
822            if dlg.ShowModal() == wx.ID_OK:
823                self.GSASprojectfile = dlg.GetPath()
824                G2IO.ProjFileSave(self)
825                self.dirname = dlg.GetDirectory()
826        finally:
827            dlg.Destroy()
828
829    def ExitMain(self, event):
830        sys.exit()
831       
832    def OnFileExitMenu(self, event):
833        if self.dataFrame:
834            self.dataFrame.Clear() 
835            self.dataFrame.Destroy()
836        pylab.close('all')
837        self.Close()
838       
839    def OnImportPattern(self,event):
840            dlg = wx.FileDialog(self, 'Choose nonGSAS powder file', '.', '', 
841                '(*.*)|*.*',wx.OPEN)
842            if self.dirname:
843                dlg.SetDirectory(self.dirname)
844            try:
845                if dlg.ShowModal() == wx.ID_OK:
846                    self.powderfile = dlg.GetPath()
847                    self.dirname = dlg.GetDirectory()
848            finally:
849                dlg.Destroy()
850               
851    def OnImportHKL(self,event):
852            dlg = wx.FileDialog(self, 'Choose structure factor file', '.', '', 
853                '(*.*)|*.*',wx.OPEN)
854            if self.dirname:
855                dlg.SetDirectory(self.dirname)
856            try:
857                if dlg.ShowModal() == wx.ID_OK:
858                    self.HKLfile = dlg.GetPath()
859                    self.dirname = dlg.GetDirectory()
860            finally:
861                dlg.Destroy()
862       
863    def OnImportPhase(self,event):
864            dlg = wx.FileDialog(self, 'Choose GSAS EXP file', '.', '', 
865                'EXP file (*.EXP)|*.EXP',wx.OPEN)
866            if self.dirname:
867                dlg.SetDirectory(self.dirname)
868            try:
869                Phase = {}
870                if dlg.ShowModal() == wx.ID_OK:
871                    EXPfile = dlg.GetPath()
872                    self.dirname = dlg.GetDirectory()
873                    Phase = G2IO.ReadEXPPhase(EXPfile)
874            finally:
875                dlg.Destroy()
876            if Phase:
877                PhaseName = Phase['General'][0]
878                if not G2gd.GetPatternTreeItemId(self,self.root,'Phases'):
879                    sub = self.PatternTree.AppendItem(parent=self.root,text='Phases')
880                else:
881                    sub = G2gd.GetPatternTreeItemId(self,self.root,'Phases')
882                sub = self.PatternTree.AppendItem(parent=sub,text=PhaseName)
883                self.PatternTree.SetItemPyData(sub,Phase)
884               
885    def OnImportPDB(self,event):
886            dlg = wx.FileDialog(self, 'Choose PDB file', '.', '', 
887                'PDB file (*.pdb,*.ent)|*.pdb;*.ent|All files (*.*)|*.*',wx.OPEN)
888            if self.dirname:
889                dlg.SetDirectory(self.dirname)
890            try:
891                if dlg.ShowModal() == wx.ID_OK:
892                    PDBfile = dlg.GetPath()
893                    self.dirname = dlg.GetDirectory()
894                    Phase = G2IO.ReadPDBPhase(PDBfile)
895            finally:
896                dlg.Destroy()
897            if Phase:
898                PhaseName = Phase['General'][0]
899                if not G2gd.GetPatternTreeItemId(self,self.root,'Phases'):
900                    sub = self.PatternTree.AppendItem(parent=self.root,text='Phases')
901                else:
902                    sub = G2gd.GetPatternTreeItemId(self,self.root,'Phases')
903                sub = self.PatternTree.AppendItem(parent=sub,text=PhaseName)
904                self.PatternTree.SetItemPyData(sub,Phase)       
905       
906    def OnImportCIF(self,event):
907            dlg = wx.FileDialog(self, 'Choose CIF file', '.', '', 
908                'CIF file (*.cif)|*.cif',wx.OPEN)
909            if self.dirname:
910                dlg.SetDirectory(self.dirname)
911            try:
912                if dlg.ShowModal() == wx.ID_OK:
913                    self.CIFfile = dlg.GetPath()
914                    self.dirname = dlg.GetDirectory()
915            finally:
916                dlg.Destroy()
917       
918    def OnExportPattern(self,event):
919        dlg = wx.FileDialog(self, 'Choose output powder file name', '.', '', 
920            'xye file (*.xye)|*.xye',wx.FD_SAVE|wx.FD_OVERWRITE_PROMPT)
921        if self.dirname:
922            dlg.SetDirectory(self.dirname)
923        try:
924            if dlg.ShowModal() == wx.ID_OK:
925                self.powderfile = dlg.GetPath()
926                G2IO.PowderxyeSave(self)
927                self.dirname = dlg.GetDirectory()
928        finally:
929            dlg.Destroy()
930       
931    def OnExportPeakList(self,event):
932        dlg = wx.FileDialog(self, 'Choose output peak list file name', '.', '', 
933            '(*.*)|*.*',wx.FD_SAVE|wx.FD_OVERWRITE_PROMPT)
934        if self.dirname:
935            dlg.SetDirectory(self.dirname)
936        try:
937            if dlg.ShowModal() == wx.ID_OK:
938                self.peaklistfile = dlg.GetPath()
939                file = open(self.peaklistfile,'wa')               
940                item, cookie = self.PatternTree.GetFirstChild(self.root)
941                while item:
942                    name = self.PatternTree.GetItemText(item)
943                    if 'PWDR' in name:
944                        item2, cookie2 = self.PatternTree.GetFirstChild(item)
945                        while item2:
946                            name2 = self.PatternTree.GetItemText(item2)
947                            if name2 == 'Peak List':
948                                peaks = self.PatternTree.GetItemPyData(item2)
949                                file.write("%s \n" % (name+' Peak List'))               
950                                for peak in peaks:
951                                    file.write("%10.4f %12.2f %10.3f %10.3f \n" % \
952                                        (peak[0],peak[2],peak[4],peak[6]))
953                            item2, cookie2 = self.PatternTree.GetNextChild(item, cookie2)                           
954                    item, cookie = self.PatternTree.GetNextChild(self.root, cookie)                           
955                file.close()
956                self.dirname = dlg.GetDirectory()
957        finally:
958            dlg.Destroy()
959       
960    def OnExportHKL(self,event):
961        event.Skip()
962       
963    def OnExportPhase(self,event):
964        event.Skip()
965       
966    def OnExportCIF(self,event):
967        event.Skip()
968       
969    def OnUnDo(self,event):
970        self.DoUnDo()
971        self.UnDo.Enable(False)
972       
973    def DoUnDo(self):
974        print 'Undo last refinement'
975        file = open('GSASII.save','rb')
976        PatternId = self.PatternId
977        for item in ['Background','Instrument Parameters','Peak List']:
978            self.PatternTree.SetItemPyData(G2gd.GetPatternTreeItemId(self,PatternId, item),cPickle.load(file))
979            if self.dataDisplay.GetName() == item:
980                if item == 'Background':
981                    G2gd.UpdateBackgroundGrid(self,self.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(self,PatternId, item)))
982                elif item == 'Instrument Parameters':
983                    G2gd.UpdateInstrumentGrid(self,self.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(self,PatternId, item)))
984                elif item == 'Peak List':
985                    G2gd.UpdatePeakGrid(self,self.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(self,PatternId, item)))
986            print item,' recovered'
987        file.close()
988       
989    def OnPeakFit(self,event):
990        self.SaveState()
991        print 'Peak Fitting - Do one cycle of peak fitting'
992        PatternId = self.PatternId
993        PickId = self.PickId
994        peaks = self.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(self,PatternId, 'Peak List'))
995        if not peaks:
996            self.ErrorDialog('No peaks!','Nothing to fit!')
997            return
998        background = self.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(self,PatternId, 'Background'))[0]
999        limits = self.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(self,PatternId, 'Limits'))[1]
1000        inst = self.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(self,PatternId, 'Instrument Parameters'))
1001        data = self.PatternTree.GetItemPyData(PatternId)[1]
1002        OK,smin,Rwp,runtime,GoOn = G2cmp.DoPeakFit(peaks,background,limits,inst,data)
1003        G2gd.UpdatePeakGrid(self,peaks)
1004        self.PlotPatterns()
1005        if not OK:
1006            print 'Refinement failed'
1007            dlg = wx.MessageDialog(self, 'Do you want to reload now?', 'Refinement failed',  wx.YES_NO)
1008            try:
1009                if dlg.ShowModal() == wx.ID_YES:
1010                    self.DoUnDo()
1011                    self.UnDo.Enable(False)
1012            finally:
1013                dlg.Destroy()
1014        else:
1015            print "%s%7.2f%s%12.6g" % ('Rwp = ',Rwp,'%, Smin = ',smin)
1016            print "%s%8.3f%s " % ('fitpeak time =',runtime,'s')
1017            print 'finished'
1018        return
1019       
1020    def OnAutoPeakFit(self,event):
1021        self.SaveState()
1022        print 'AutoPeak Fitting - run until minimized'
1023        PatternId = self.PatternId
1024        PickId = self.PickId
1025        peaks = self.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(self,PatternId, 'Peak List'))
1026        if not peaks:
1027            self.ErrorDialog('No peaks!','Nothing to fit!')
1028            return
1029        background = self.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(self,PatternId, 'Background'))[0]
1030        limits = self.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(self,PatternId, 'Limits'))[1]
1031        inst = self.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(self,PatternId, 'Instrument Parameters'))
1032        data = self.PatternTree.GetItemPyData(PatternId)[1]
1033        smin = 1.0e10
1034        GoOn = True
1035        while GoOn:
1036            osmin = smin
1037            OK,smin,Rwp,runtime,GoOn = G2cmp.DoPeakFit(peaks,background,limits,inst,data)
1038            print GoOn
1039            G2gd.UpdatePeakGrid(self,peaks)
1040            if not OK:
1041                break
1042            self.PlotPatterns()
1043            print "%s%7.2f%s%12.6g" % ('Rwp = ',Rwp,'%, Smin = ',smin)
1044            rat = (osmin-smin)/smin
1045            if rat < 1.0e-4: GoOn = False
1046        if not OK:
1047            print 'Refinement failed'
1048            dlg = wx.MessageDialog(self, 'Do you want to reload now?', 'Refinement failed',  wx.YES_NO)
1049            try:
1050                if dlg.ShowModal() == wx.ID_YES:
1051                    self.DoUnDo()
1052                    self.UnDo.Enable(False)
1053            finally:
1054                dlg.Destroy()
1055        else:
1056            print "%s%8.3f%s " % ('fitpeak time =',runtime,'s per cycle')
1057            print 'finished'
1058        return
1059       
1060    def OnRefineCell(self,event):
1061        def cellPrint(ibrav,A):
1062            cell = G2cmp.A2cell(A)
1063            Vol = G2cmp.calc_V(A)
1064            if ibrav in [0,1,2]:
1065                print "%s%10.6f" % ('a =',cell[0])
1066            elif ibrav in [3,4,5,6]:
1067                print "%s%10.6f %s%10.6f %s%12.3f" % ('a =',cell[0],' c =',cell[2],' volume =',Vol)
1068            elif ibrav in [7,8,9,10]:
1069                print "%s%10.6f %s%10.6f %s%10.6f %s%12.3f" % ('a =',cell[0],'b =',cell[1],'c =',cell[2],' volume =',Vol)
1070            elif ibrav in [11,12]:
1071                print "%s%10.6f %s%10.6f %s%10.6f %s%8.3f %s%12.3f" % ('a =',cell[0],'b =',cell[1],'c =',cell[2],'beta =',cell[4],' volume =',Vol)
1072            else:
1073                print "%s%10.6f %s%10.6f %s%10.6f" % ('a =',cell[0],'b =',cell[1],'c =',cell[2])
1074                print "%s%8.3f %s%8.3f %s%8.3f %s%12.3f" % ('alpha =',cell[3],'beta =',cell[4],'gamma =',cell[5],' volume =',Vol)
1075             
1076        bravaisSymb = ['Fm3m','Im3m','Pm3m','R3-H','P6/mmm','I4/mmm',
1077            'P4/mmm','Fmmm','Immm','Cmmm','Pmmm','C2/m','P2/m','P1']
1078        PatternId = self.PatternId
1079        PickId = self.PickId   
1080        peaks = self.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(self,PatternId, 'Index Peak List'))
1081        if not peaks:
1082            self.ErrorDialog('No peaks!', 'Nothing to refine!')
1083            return       
1084        print 'Refine cell'
1085        inst = self.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(self,PatternId, 'Instrument Parameters'))[1]
1086        controls,bravais,cells,dmin = self.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(self,PatternId, 'Unit Cells List'))
1087        cell = controls[6:12]
1088        A = G2cmp.cell2A(cell)
1089        print controls[5]
1090        ibrav = bravaisSymb.index(controls[5])
1091        dmin = G2cmp.getDmin(peaks)-0.05
1092        Lhkl,M20,X20 = G2cmp.refinePeaks(peaks,ibrav,A)
1093        controls[6:12] = G2cmp.A2cell(A)
1094        controls[12] = G2cmp.calc_V(A)
1095        data = [controls,bravais,cells,dmin]
1096        self.PatternTree.SetItemPyData(G2gd.GetPatternTreeItemId(self,PatternId, 'Unit Cells List'),data)
1097        self.HKL = G2cmp.GenHBravais(dmin,ibrav,A)
1098        G2gd.UpdateUnitCellsGrid(self,data)
1099        print "%s%10.3f" % ('refinement M20 = ',M20)
1100        print 'unindexed lines = ',X20
1101        cellPrint(ibrav,A)
1102        for hkl in self.HKL:
1103            hkl.append(2.0*asind(inst[1]/(2.*hkl[3])))             
1104        self.PlotPatterns()
1105       
1106    def SaveState(self):
1107        file = open('GSASII.save','wb')
1108        PatternId = self.PatternId
1109        for item in ['Background','Instrument Parameters','Peak List']:
1110            cPickle.dump(self.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(self,PatternId,item)),file,1)
1111        file.close()
1112        self.UnDo.Enable(True)
1113         
1114    def OnIndexPeaks(self,event):
1115        PatternId = self.PatternId   
1116        peaks = self.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(self,PatternId, 'Index Peak List'))
1117        if not peaks:
1118            self.ErrorDialog('No peaks!', 'Nothing to index!')
1119            return
1120        inst = self.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(self,PatternId, 'Instrument Parameters'))[1]
1121        print 'Peak Indexing'
1122        try:
1123            controls,bravais,cells,dmin = self.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(self,PatternId, 'Unit Cells List'))
1124            cells = []
1125        except ValueError:
1126            self.ErrorDialog('Error','Need to set controls in Unit Cell List first')
1127            return
1128        if True not in bravais:
1129            self.ErrorDialog('Error','No Bravais lattices selected')
1130            return
1131        self.IndexPeaks.Enable(False)
1132        self.RefineCell.Enable(False)
1133        OK,dmin,cells = G2cmp.DoIndexPeaks(peaks,inst,controls,bravais)
1134        if OK:
1135            data = [controls,bravais,cells,dmin]
1136            self.PatternTree.SetItemPyData(G2gd.GetPatternTreeItemId(self,PatternId, 'Unit Cells List'),data)
1137            G2gd.UpdateUnitCellsGrid(self,data)
1138            bestCell = cells[0]
1139            if bestCell[0] > 10.:
1140                self.HKL = G2cmp.GenHBravais(dmin,bestCell[2],G2cmp.cell2A(bestCell[3:9]))
1141                for hkl in self.HKL:
1142                    hkl.append(2.0*asind(inst[1]/(2.*hkl[3])))             
1143                self.PlotPatterns()
1144        self.RefineCell.Enable(True)
1145        self.IndexPeaks.Enable(True)
1146
1147    def PlotPeakWidths(self):
1148        newPlot = False 
1149        PatternId = self.PatternId
1150        limitID = G2gd.GetPatternTreeItemId(self,PatternId, 'Limits')
1151        if limitID:
1152            limits = self.PatternTree.GetItemPyData(limitID)
1153        else:
1154            return
1155        instParms = self.PatternTree.GetItemPyData( \
1156            G2gd.GetPatternTreeItemId(self,PatternId, 'Instrument Parameters'))
1157        if instParms[0][0] == 'PXC':
1158            lam = instParms[1][1]
1159            if len(instParms[1]) == 12:
1160                GU,GV,GW,LX,LY = instParms[0][6:11]
1161            else:
1162                GU,GV,GW,LX,LY = instParms[0][4:9]
1163        peakID = G2gd.GetPatternTreeItemId(self,PatternId, 'Peak List')
1164        if peakID:
1165            peaks = self.PatternTree.GetItemPyData(peakID)
1166        else:
1167            peaks = []
1168        try:
1169            self.pdplot.clear()
1170            self.pdplot.canvas.set_window_title('Peak Widths')
1171        except:
1172            self.pdplot.clear()
1173            self.pdplot = pylab.figure(facecolor='white')
1174            self.pdplot.canvas.set_window_title('Peak Widths')
1175            self.NewPlot = True
1176            newPlot = True
1177        self.pdplot.canvas.SetToolTipString('')
1178        colors=['b','g','r','c','m','k']
1179        Xmin,Xmax = limits[1]
1180        Xmin = min(0.5,max(Xmin,1))
1181        Xmin /= 2
1182        Xmax /= 2
1183        nPts = 100
1184        delt = (Xmax-Xmin)/nPts
1185        thetas = []
1186        for i in range(nPts):
1187            thetas.append(Xmin+i*delt)
1188        X = []
1189        Y = []
1190        Z = []
1191        W = []
1192        sig = lambda Th,U,V,W: 1.17741*math.sqrt(U*tand(Th)**2+V*tand(Th)+W)*math.pi/18000.
1193        gam = lambda Th,X,Y: (X/cosd(Th)+Y*tand(Th))*math.pi/18000.
1194        gamFW = lambda s,g: math.exp(math.log(g**5+2.69269*g**4*s+2.42843*g**3*s**2+4.47163*g**2*s**3+0.07842*g*s**4+s**5)/5.)
1195        for theta in thetas:
1196            X.append(4.0*math.pi*sind(theta)/lam)              #q
1197            s = sig(theta,GU,GV,GW)
1198            g = gam(theta,LX,LY)
1199            G = gamFW(g,s)
1200            Y.append(s/tand(theta))
1201            Z.append(g/tand(theta))
1202            W.append(G/tand(theta))
1203        ax = self.pdplot.add_subplot(111)
1204        ax.clear()
1205        ax.set_title('Instrument and sample peak widths')
1206        ax.set_ylabel(r'$\Delta q/q, \Delta d/d$',fontsize=14)
1207        ax.set_xlabel(r'$q, \AA^{-1}$',fontsize=14)
1208        ax.plot(X,Y,color='r',label='Gaussian')
1209        ax.plot(X,Z,color='g',label='Lorentzian')
1210        ax.plot(X,W,color='b',label='G+L')
1211        X = []
1212        Y = []
1213        Z = []
1214        W = []
1215        for peak in peaks:
1216            X.append(4.0*math.pi*sind(peak[0]/2.0)/lam)
1217            s = 1.17741*math.sqrt(peak[4])*math.pi/18000.
1218            g = peak[6]*math.pi/18000.
1219            G = gamFW(g,s)
1220            Y.append(s/tand(peak[0]/2.))
1221            Z.append(g/tand(peak[0]/2.))
1222            W.append(G/tand(peak[0]/2.))
1223        ax.plot(X,Y,'+',color='r',label='G peak')
1224        ax.plot(X,Z,'+',color='g',label='L peak')
1225        ax.plot(X,W,'+',color='b',label='G+L peak')
1226        ax.legend(loc='best')
1227        self.NewPlot = True
1228           
1229        if newPlot:
1230            pylab.show()
1231        else:                       #1st plot
1232            pylab.draw()
1233           
1234    def PlotImage(self):
1235
1236        def OnImMotion(event):
1237            if event.xdata:
1238                item = self.itemPicked
1239                if item:
1240                    xpos = event.xdata
1241                    if xpos:                                        #avoid out of frame mouse position
1242                        ypos = event.ydata
1243                        xcent,ycent = Data['center']
1244                        xpos -= xcent*scalex
1245                        ypos -= ycent*scaley
1246                        if 'Text' in str(item):
1247                            self.pdplot.canvas.SetToolTipString('%8.3f %8.3fmm'%(event.xdata/scalex,event.ydata/scaley))
1248                        else:
1249#                            xpos /= radius
1250#                            ypos /= radius
1251                            if 'line2' in  str(item) or 'line3' in str(item):
1252                                ang = int(atan2d(-ypos,xpos))
1253                                self.pdplot.canvas.SetToolTipString('%6d deg'%(ang))
1254                            else:
1255                                radius = math.sqrt(xpos**2+ypos**2)
1256                                self.pdplot.canvas.SetToolTipString('%8.3fmm'%(radius/scalex))
1257                           
1258                else:
1259                    size = len(self.ImageZ)
1260                    xpos = int(event.xdata)*self.imScale
1261                    ypos = int(event.ydata)*self.imScale
1262                    if (0 < xpos < size) and (0 < ypos < size):     #avoid out of image position
1263                        z = self.ImageZ[ypos][xpos]
1264                        self.pdplot.canvas.SetToolTipString('%6d'%(z))
1265
1266        def OnImPlotKeyPress(event):
1267            if self.PatternTree.GetItemText(self.PickId) == 'Image Controls':
1268                Data = self.PatternTree.GetItemPyData(self.PickId)
1269                pixelSize = Data['pixelSize']
1270                size = len(self.ImageZ)
1271                Xpos = event.xdata
1272                if Xpos:
1273                    Xpos = int(Xpos)*self.imScale
1274                else:                   #got point out of frame
1275                    return
1276                Ypos = int(event.ydata)*self.imScale
1277                if event.key == 'c':
1278                    cent = Data['center'] = [Xpos*pixelSize[0]/1000.,Ypos*pixelSize[1]/1000.] #convert to mm
1279                    self.centText.SetValue(("%8.3f,%8.3f" % (cent[0],cent[1])))
1280                elif event.key == 'r':
1281                    w = 20
1282                    w2 = w*2
1283                    Z = self.ImageZ[Ypos-w:Ypos+w,Xpos-w:Xpos+w]
1284                    Zmax = np.argmax(Z)
1285                    Xpos += Zmax%w2-w
1286                    Ypos += Zmax/w2-w
1287                    xpos = Xpos*pixelSize[0]/1000.
1288                    ypos = Ypos*pixelSize[1]/1000.
1289                    Data['ring'].append([xpos,ypos])
1290                elif event.key == 'm':
1291                    xpos = Xpos*pixelSize[0]/1000.
1292                    ypos = Ypos*pixelSize[1]/1000.
1293                    print 'mask = ',xpos,ypos
1294                self.PlotImage()
1295               
1296        def OnImPick(event):
1297            if self.itemPicked is not None: return
1298            pick = event.artist
1299            self.itemPicked = pick
1300           
1301        def OnImRelease(event):
1302            if self.itemPicked is None: return
1303            xpos = event.xdata
1304            if xpos:                                        #avoid out of frame mouse position
1305                xcent,ycent = Data['center']
1306                xcent *= scalex
1307                ycent *= scaley
1308                ypos = event.ydata
1309                xpos -= xcent
1310                ypos -= ycent
1311                radius = math.sqrt(xpos**2+ypos**2)
1312                xpos /= radius
1313                ypos /= radius
1314                ang = int(atan2d(-ypos,xpos))
1315                if 'Line2D' in str(self.itemPicked):
1316                    if 'line2' in str(self.itemPicked):
1317                        Data['LRazimuth'][0] = ang
1318                    elif 'line3' in str(self.itemPicked):
1319                        Data['LRazimuth'][1] = ang
1320                    elif 'line0' in str(self.itemPicked):
1321                        Data['IOradii'][0] = radius/scalex
1322                    elif 'line1' in str(self.itemPicked):
1323                        Data['IOradii'][1] = radius/scalex
1324                    if Data['LRazimuth'][1] < Data['LRazimuth'][0]:
1325                        Data['LRazimuth'][1] += 360
1326                    if  Data['IOradii'][0] > Data['IOradii'][1]:
1327                        Data['IOradii'] = G2cmp.SwapXY(Data['IOradii'][0],Data['IOradii'][1])
1328                    self.IOradText.SetValue("%8.3f,%8.3f" % (Data['IOradii'][0],Data['IOradii'][1]))
1329                    self.LRazim.SetValue("%6d,%6d" % (Data['LRazimuth'][0],Data['LRazimuth'][1]))
1330                elif 'Text' in str(self.itemPicked):
1331                    cent = Data['center'] = [event.xdata/scalex,event.ydata/scalex]
1332                    try:
1333                        self.centText.SetValue(("%8.3f,%8.3f" % (cent[0],cent[1])))
1334                    except AttributeError:
1335                        pass
1336                self.PlotImage()
1337            self.itemPicked = None
1338           
1339
1340        newPlot = False
1341        self.NewPlot = True 
1342        try:
1343            self.pdplot.clear()
1344            self.pdplot.canvas.toolbar.set_history_buttons()
1345            self.pdplot.canvas.set_window_title('2D Powder Image')
1346        except:
1347            self.pdplot = pylab.figure(facecolor='white')
1348            self.pdplot.clear()
1349            self.pdplot.canvas.set_window_title('2D Powder Image')
1350            self.pdplot.canvas.mpl_connect('key_press_event', OnImPlotKeyPress)
1351            self.pdplot.canvas.mpl_connect('motion_notify_event', OnImMotion)
1352            self.pdplot.canvas.mpl_connect('pick_event', OnImPick)
1353            self.pdplot.canvas.mpl_connect('button_release_event', OnImRelease)
1354            self.NewPlot = True                     #to make sure subsequent 1-D plot will be OK
1355            newPlot = True
1356        PickId = self.PickId
1357        ax = self.pdplot.add_subplot(111)
1358        size,self.ImageZ = self.PatternTree.GetItemPyData(self.Image)
1359        Data = self.PatternTree.GetItemPyData( \
1360            G2gd.GetPatternTreeItemId(self,self.Image, 'Image Controls'))
1361        self.imScale = 1
1362        if len(self.ImageZ) > 1024:
1363            self.imScale = len(self.ImageZ)/1024
1364        xmax = len(self.ImageZ)/self.imScale
1365        xlim = (-0.5,xmax-.5)
1366        ylim = (xmax-.5,-0.5,)
1367        if self.Img:
1368            xlim = self.Img.axes.get_xlim()
1369            ylim = self.Img.axes.get_ylim()
1370        pixelSize = Data['pixelSize']
1371        scalex = 1000./(pixelSize[0]*self.imScale)
1372        scaley = 1000./(pixelSize[1]*self.imScale)
1373        Imin,Imax = Data['range'][1]
1374        acolor = mpl.cm.get_cmap(Data['color'])
1375        xcent,ycent = Data['center']
1376        xcent *= scalex
1377        ycent *= scaley
1378        ax.set_xlabel('Image x-axis/'+str(self.imScale),fontsize=12)
1379        ax.set_ylabel('Image y-axis/'+str(self.imScale),fontsize=12)
1380        self.Img = ax.imshow(self.ImageZ[::self.imScale,::self.imScale], \
1381            aspect='equal',origin='upper',cmap=acolor, \
1382            interpolation='nearest',vmin=Imin,vmax=Imax)
1383        ax.text(xcent,ycent,'+',ha='center',va='center',picker=3)
1384        if Data['showLines']:
1385            LRAzim = Data['LRazimuth']
1386            IOradii = Data['IOradii']
1387            arcxI = arcyI = np.array(range(LRAzim[0],LRAzim[1]+1))
1388            arcxI = np.sin(arcxI*math.pi/180.)*scalex*Data['IOradii'][0]+xcent
1389            arcyI = -np.cos(arcyI*math.pi/180.)*scaley*Data['IOradii'][0]+ycent
1390            ax.plot(arcxI,arcyI,picker=3)
1391            arcxO = arcyO = np.array(range(LRAzim[0],LRAzim[1]+1))
1392            arcxO = np.sin(arcxO*math.pi/180.)*scalex*Data['IOradii'][1]+xcent
1393            arcyO = -np.cos(arcyO*math.pi/180.)*scaley*Data['IOradii'][1]+ycent
1394            ax.plot(arcxO,arcyO,picker=3)
1395            xbeg = arcxI[0]
1396            ybeg = arcyI[0]
1397            ax.plot([xbeg,sind(LRAzim[0])*IOradii[1]*scalex+xcent],
1398                [ybeg,-cosd(LRAzim[0])*IOradii[1]*scaley+ycent],picker=3)
1399            xbeg = arcxI[-1]
1400            ybeg = arcyI[-1]
1401            ax.plot([xbeg,sind(LRAzim[1])*IOradii[1]*scalex+xcent],
1402                [ybeg,-cosd(LRAzim[1])*IOradii[1]*scaley+ycent],picker=3)
1403        for xring,yring in Data['ring']:
1404            xring *= scalex
1405            yring *= scaley
1406            ax.text(xring,yring,'+',ha='center',va='center')
1407        self.Img.axes.set_xlim(xlim)
1408        self.Img.axes.set_ylim(ylim)
1409        self.pdplot.colorbar(self.Img)
1410        if newPlot:
1411            pylab.show()
1412        else:                       #1st plot
1413            pylab.draw()
1414       
1415               
1416    def PlotPatterns(self):
1417       
1418        def OnPick(event):
1419            if self.itemPicked is not None: return
1420            PatternId = self.PatternId
1421            PickId = self.PickId
1422            pick = event.artist
1423            mouse = event.mouseevent
1424            xpos = pick.get_xdata()
1425            ypos = pick.get_ydata()
1426            ind = event.ind
1427            xy = zip(xpos[ind],ypos[ind])
1428            if self.PatternTree.GetItemText(PickId) == 'Peak List':
1429                if ind.all() != [0]:                                    #picked a data point
1430                    inst = self.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(self,PatternId, 'Instrument Parameters'))
1431                    if len(inst[1]) == 10:
1432                        ins = inst[1][4:10]
1433                    else:
1434                        ins = inst[1][6:12]   
1435                    sig = ins[0]*tand(xy[0][0]/2.0)**2+ins[1]*tand(xy[0][0]/2.0)+ins[2]
1436                    gam = ins[3]/cosd(xy[0][0]/2.0)+ins[4]*tand(xy[0][0]/2.0)           
1437                    data = self.PatternTree.GetItemPyData(self.PickId)
1438                    XY = [xy[0][0],0, xy[0][1],1, sig,0, gam,0, ins[5],0]       #default refine intensity 1st   
1439                    data.append(XY)
1440                    G2gd.UpdatePeakGrid(self,data)
1441                else:                                                   #picked a peak list line
1442                    self.itemPicked = pick
1443            elif self.PatternTree.GetItemText(PickId) == 'Limits':
1444                if ind.all() != [0]:                                    #picked a data point
1445                    LimitId = G2gd.GetPatternTreeItemId(self,PatternId, 'Limits')
1446                    data = self.PatternTree.GetItemPyData(LimitId)
1447                    if mouse.button==1:
1448                        data[1][0] = min(xy[0][0],data[1][1])
1449                    if mouse.button==3:
1450                        data[1][1] = max(xy[0][0],data[1][0])
1451                    self.PatternTree.SetItemPyData(LimitId,data)
1452                    G2gd.UpdateLimitsGrid(self,data)
1453                else:                                                   #picked a limit line
1454                    self.itemPicked = pick               
1455            self.PlotPatterns()
1456           
1457        def OnPlotKeyPress(event):
1458            if event.key == 'w':
1459                if self.Weight:
1460                    self.Weight = False
1461                else:
1462                    self.Weight = True
1463                self.PlotPatterns()
1464                print 'plot weighting:',self.Weight
1465            if self.PatternTree.GetChildrenCount(self.root,False) > 1:
1466                if event.key == 'u' and self.Offset < 100.:
1467                    self.Offset += 1.
1468                    self.PlotPatterns()
1469                elif event.key == 'd' and self.Offset > 0.:
1470                    self.Offset -= 1.
1471                    self.PlotPatterns()
1472                elif event.key == 'c':
1473                    print 'contouring'
1474                    if self.Contour:
1475                        self.Contour = False
1476                    else:
1477                        self.Contour = True
1478                    self.PlotPatterns()
1479    #            elif self.Contour and event.key == 'l':
1480    #                event.StopPropagation()
1481            else:
1482                event.Skip()
1483                           
1484        def OnMotion(event):
1485            if self.itemPicked:
1486                xpos = event.xdata
1487                if xpos:                                        #avoid out of frame mouse position
1488                    self.pdplot.canvas.SetToolTipString('%9.3f'%(xpos))
1489                       
1490        def OnRelease(event):
1491            if self.itemPicked is None: return
1492            xpos = event.xdata
1493            if xpos:                                        #avoid out of frame mouse position
1494                lines = []
1495                for line in self.Lines: lines.append(line.get_xdata()[0])
1496                lineNo = lines.index(self.itemPicked.get_xdata()[0])
1497                if  lineNo in [0,1]:
1498                    LimitId = G2gd.GetPatternTreeItemId(self,self.PatternId, 'Limits')
1499                    data = self.PatternTree.GetItemPyData(LimitId)
1500                    data[1][lineNo] = xpos
1501                    self.PatternTree.SetItemPyData(LimitId,data)
1502                    if self.PatternTree.GetItemText(self.PickId) == 'Limits':
1503                        G2gd.UpdateLimitsGrid(self,data)
1504                else:
1505                    PeakId = G2gd.GetPatternTreeItemId(self,self.PatternId, 'Peak List')
1506                    data = self.PatternTree.GetItemPyData(PeakId)
1507                    data[lineNo-2][0] = xpos
1508                    self.PatternTree.SetItemPyData(PeakId,data)
1509                    G2gd.UpdatePeakGrid(self,data)
1510            self.PlotPatterns()
1511            self.itemPicked = None   
1512           
1513        try:
1514            if self.NewPlot:
1515                self.pdplot.clear()
1516            self.pdplot.canvas.toolbar.set_history_buttons()
1517            self.pdplot.canvas.set_window_title('Powder Patterns')
1518        except:
1519            self.pdplot = pylab.figure(facecolor='white')
1520            self.pdplot.clear()
1521            self.pdplot.canvas.set_window_title('Powder Patterns')
1522            self.pdplot.canvas.mpl_connect('key_press_event', OnPlotKeyPress)
1523            self.pdplot.canvas.mpl_connect('pick_event', OnPick)
1524            self.pdplot.canvas.mpl_connect('button_release_event', OnRelease)
1525            self.pdplot.canvas.mpl_connect('motion_notify_event', OnMotion)
1526            self.NewPlot = True
1527        PickId = self.PickId
1528        PatternId = self.PatternId
1529        colors=['b','g','r','c','m','k']
1530        Ymax = 1.0
1531        PlotList = []
1532        Lines = []
1533        item, cookie = self.PatternTree.GetFirstChild(self.root)
1534        while item:
1535            if 'PWDR' in self.PatternTree.GetItemText(item):
1536                Pattern = self.PatternTree.GetItemPyData(item)
1537                Pattern.append(self.PatternTree.GetItemText(item))
1538                PlotList.append(Pattern)
1539            item, cookie = self.PatternTree.GetNextChild(self.root, cookie)               
1540        for Pattern in PlotList:
1541            xye = Pattern[1]
1542            Ymax = max(Ymax,max(xye[1]))
1543        offset = self.Offset*Ymax/100.0
1544        ax = self.pdplot.add_subplot(111)
1545        ax.cla()
1546        if not self.NewPlot:
1547            xlim = ax.get_xlim()
1548            ylim = ax.get_ylim()
1549        ax.clear()
1550        ax.set_title('Powder Patterns')
1551        ax.set_xlabel(r'$\mathsf{2\theta}$',fontsize=14)
1552        ax.set_ylabel('Intensity',fontsize=12)
1553        if self.Contour:
1554            ContourZ = []
1555            ContourY = []
1556            Nseq = 0
1557        for Pattern in PlotList:
1558            ifpicked = False
1559            LimitId = 0
1560            if PickId:
1561                ifpicked = Pattern[2] in self.PatternTree.GetItemText(PatternId)
1562                LimitId = G2gd.GetPatternTreeItemId(self,PatternId, 'Limits')
1563            xye = Pattern[1]
1564            N = PlotList.index(Pattern)
1565            X = np.array(xye[0])
1566            Y = np.array(xye[1])
1567            Y += offset*N
1568            if LimitId:
1569                limits = self.PatternTree.GetItemPyData(LimitId)
1570                Lines.append(ax.axvline(limits[1][0],color='g',dashes=(5,5),picker=3))   
1571                Lines.append(ax.axvline(limits[1][1],color='r',dashes=(5,5),picker=3))                   
1572            if self.Contour:
1573                ContourY.append(N)
1574                ContourZ.append(Y)
1575                ContourX = X
1576                Nseq += 1
1577                ax.set_ylabel('Data sequence',fontsize=12)
1578            else:
1579                if ifpicked:
1580                    Z = np.array(xye[3])+offset*N
1581                    W = np.array(xye[4])+offset*N
1582                    D = np.array(xye[5])+offset*N
1583                    if self.Weight:
1584                        W2 = np.sqrt(np.array(xye[2]))
1585                        D *= W2
1586                    ax.plot(X,Y,colors[N%6]+'+',picker=3)
1587                    ax.plot(X,Z,colors[(N+1)%6],picker=False)
1588                    ax.plot(X,W,colors[(N+2)%6],picker=False)
1589                    ax.plot(X,D,colors[(N+3)%6],picker=False)
1590                    ax.axhline(0.,color=wx.BLACK)
1591                    self.pdplot.canvas.SetToolTipString('')
1592                    if self.PatternTree.GetItemText(PickId) == 'Peak List':
1593                        tip = 'On data point: Pick peak - L or R MB.On line: MB down to move'
1594                        self.pdplot.canvas.SetToolTipString(tip)
1595                        data = self.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(self,PatternId, 'Peak List'))
1596                        for item in data:
1597                            Lines.append(ax.axvline(item[0],color=colors[N%6],picker=2))
1598                    if self.PatternTree.GetItemText(PickId) == 'Limits':
1599                        tip = 'On data point: Lower limit - L MB; Upper limit - R MB. On limit: MB down to move'
1600                        self.pdplot.canvas.SetToolTipString(tip)
1601                        data = self.LimitsTable.GetData()
1602                else:
1603                    ax.plot(xye[0],Y,colors[N%6],picker=False)
1604        if PickId and self.PatternTree.GetItemText(PickId) in ['Index Peak List','Unit Cells List']:
1605            peaks = self.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(self,PatternId, 'Index Peak List'))
1606            for peak in peaks:
1607                ax.axvline(peak[0],color='b')
1608            for hkl in self.HKL:
1609                ax.axvline(hkl[5],color='r',dashes=(5,5))
1610            if self.NewPlot and peaks:
1611                xmin = peaks[0][0]
1612                xmax = peaks[-1][0]
1613                delt = xmax-xmin
1614                xlim = [max(0,xmin-delt/20.),min(180.,xmax+delt/20.)]
1615                ax.set_xlim(xlim)               
1616        if self.Contour:
1617            ax.contourf(ContourX,ContourY,ContourZ)
1618        self.Lines = Lines
1619        if self.NewPlot:
1620            if self.plotView:
1621                ax.set_xlim(self.plotView[0])
1622                ax.set_ylim(self.plotView[1])
1623        else:
1624            ax.set_xlim(xlim)
1625            ax.set_ylim(ylim)
1626            if self.Contour:
1627                ax.set_ylim(0,Nseq-1)
1628        if self.NewPlot:
1629            pylab.show()
1630            self.NewPlot = False
1631        else:                       #1st plot
1632            pylab.draw()
1633       
1634       
1635    def ErrorDialog(self,title,message):
1636        dlg = wx.MessageDialog(self, message, title,  wx.OK)
1637        try:
1638            result = dlg.ShowModal()
1639        finally:
1640            dlg.Destroy()
1641
1642    def OnHelpHelpMenu(self, event):
1643        event.Skip()
1644       
1645    def OnHelpAboutMenu(self, event):
1646        info = wx.AboutDialogInfo()
1647        info.Name = 'GSAS-II'
1648        info.Version = '0.0.1'
1649        info.Copyright = '''
1650Robert B. Von Dreele
1651Argonne National Laboratory(C)
1652This product includes software developed
1653by the UChicago Argonne, LLC, as
1654Operator of Argonne National Laboratory.         '''
1655        info.Description = '''
1656General Structure Analysis System - II
1657        '''
1658        wx.AboutBox(info)
1659       
1660class GSASIImain(wx.App):
1661    def OnInit(self):
1662        self.main = GSASII(None)
1663        self.main.Show()
1664        self.SetTopWindow(self.main)
1665        return True
1666
1667def main():
1668    application = GSASIImain(0)
1669    application.MainLoop()
1670
1671if __name__ == '__main__':
1672    main()
Note: See TracBrowser for help on using the repository browser.