source: trunk/GSASII.py @ 166

Last change on this file since 166 was 166, checked in by vondreele, 12 years ago

fixups of atom editing/atom drawing

File size: 56.6 KB
Line 
1#GSASII
2
3import os
4import os.path as ospath
5import sys
6import math
7import cPickle
8import time
9import copy
10import numpy as np
11import wx
12import matplotlib as mpl
13
14# load the GSAS routines
15import GSASIIpath
16import GSASIIIO as G2IO
17import GSASIIgrid as G2gd
18import GSASIIplot as G2plt
19import GSASIIpwdGUI as G2pdG
20import GSASIIspc as G2spc
21import OpenGL as ogl
22
23# print versions
24print "Available python module versions for GSASII:"
25print "python:     ",sys.version[:5]
26print "wxpython:   ",wx.__version__
27print "matplotlib: ",mpl.__version__
28print "numpy:      ",np.__version__
29print "OpenGL:     ",ogl.__version__
30
31__version__ = '0.1.4'
32
33# useful degree trig functions
34sind = lambda x: math.sin(x*math.pi/180.)
35cosd = lambda x: math.cos(x*math.pi/180.)
36tand = lambda x: math.tan(x*math.pi/180.)
37asind = lambda x: 180.*math.asin(x)/math.pi
38acosd = lambda x: 180.*math.acos(x)/math.pi
39atan2d = lambda x,y: 180.*math.atan2(y,x)/math.pi
40
41def create(parent):
42    return GSASII(parent)
43
44[wxID_PATTERNTREE, 
45] = [wx.NewId() for _init_ctrls in range(1)]
46
47[wxID_FILECLOSE, wxID_FILEEXIT, wxID_FILEOPEN, 
48 wxID_FILESAVE, wxID_FILESAVEAS, wxID_UNDO, 
49] = [wx.NewId() for _init_coll_File_Items in range(6)]
50
51[wxID_PWDRREAD,wxID_SNGLREAD,wxID_ADDPHASE,wxID_DELETEPHASE,
52 wxID_DATADELETE,wxID_READPEAKS,wxID_PWDSUM,wxID_IMGREAD,
53 wxID_IMSUM, wxID_DATARENAME,
54] = [wx.NewId() for _init_coll_Data_Items in range(10)]
55
56[wxID_IMPORT, wxID_IMPORTPATTERN, wxID_IMPORTHKL, wxID_IMPORTPHASE,
57wxID_IMPORTCIF, wxID_IMPORTPDB, 
58] = [wx.NewId() for _init_coll_Import_Items in range(6)]
59
60[wxID_EXPORT, wxID_EXPORTPATTERN, wxID_EXPORTHKL, wxID_EXPORTPHASE,
61wxID_EXPORTCIF, wxID_EXPORTPEAKLIST
62] = [wx.NewId() for _init_coll_Export_Items in range(6)]
63
64[wxID_HELPABOUT, wxID_HELPHELP, 
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='Open a gsasii project file (*.gpx)', id=wxID_FILEOPEN,
79             kind=wx.ITEM_NORMAL,text='Open project...')
80        parent.Append(help='SAve project to old file', id=wxID_FILESAVE, 
81            kind=wx.ITEM_NORMAL,text='Save project')
82        parent.Append(help='Save project to new file', id=wxID_FILESAVEAS, 
83            kind=wx.ITEM_NORMAL,text='Save As...')
84        parent.Append(help='Close project, saving is optional', id=wxID_FILECLOSE, 
85            kind=wx.ITEM_NORMAL,text='Close project')
86        parent.Append(help='Exit from gsasii', id=wxID_FILEEXIT, kind=wx.ITEM_NORMAL,
87            text='Exit')
88        self.Bind(wx.EVT_MENU, self.OnFileOpen, id=wxID_FILEOPEN)
89        self.Bind(wx.EVT_MENU, self.OnFileSave, id=wxID_FILESAVE)
90        self.Bind(wx.EVT_MENU, self.OnFileSaveas, id=wxID_FILESAVEAS)
91        self.Bind(wx.EVT_MENU, self.OnFileClose, id=wxID_FILECLOSE)
92        self.Bind(wx.EVT_MENU, self.OnFileExit, id=wxID_FILEEXIT)
93       
94    def _init_coll_Data_Items(self,parent):
95        parent.Append(help='', id=wxID_PWDRREAD, kind=wx.ITEM_NORMAL,
96            text='Read powder data...')
97        parent.Append(help='',id=wxID_IMGREAD, kind=wx.ITEM_NORMAL,
98            text='Read image data...')
99        parent.Append(help='',id=wxID_READPEAKS, kind=wx.ITEM_NORMAL,
100            text='Read Powder Pattern Peaks...')
101        parent.Append(help='', id=wxID_SNGLREAD, kind=wx.ITEM_NORMAL,
102            text='Read single crystal data...')
103        parent.Append(help='', id=wxID_PWDSUM, kind=wx.ITEM_NORMAL,
104            text='Sum powder data')
105        parent.Append(help='',id=wxID_IMSUM, kind=wx.ITEM_NORMAL,
106            text='Sum image data')
107        parent.Append(help='', id=wxID_ADDPHASE, kind=wx.ITEM_NORMAL,
108            text='Add phase')
109        parent.Append(help='', id=wxID_DELETEPHASE, kind=wx.ITEM_NORMAL,
110            text='Delete phase')
111        parent.Append(help='', id=wxID_DATARENAME, kind=wx.ITEM_NORMAL,
112            text='Rename data') 
113        parent.Append(help='', id=wxID_DATADELETE, kind=wx.ITEM_NORMAL,
114            text='Delete data')
115        self.Bind(wx.EVT_MENU, self.OnPwdrRead, id=wxID_PWDRREAD)
116        self.Bind(wx.EVT_MENU, self.OnPwdrSum, id=wxID_PWDSUM)
117        self.Bind(wx.EVT_MENU, self.OnReadPowderPeaks, id=wxID_READPEAKS)
118        self.Bind(wx.EVT_MENU, self.OnImageRead, id=wxID_IMGREAD)
119        self.Bind(wx.EVT_MENU, self.OnImageSum, id=wxID_IMSUM)
120        self.Bind(wx.EVT_MENU, self.OnSnglRead, id=wxID_SNGLREAD)
121        self.Bind(wx.EVT_MENU, self.OnAddPhase, id=wxID_ADDPHASE)
122        self.Bind(wx.EVT_MENU, self.OnDeletePhase, id=wxID_DELETEPHASE)
123        self.Bind(wx.EVT_MENU, self.OnRenameData, id=wxID_DATARENAME)
124        self.Bind(wx.EVT_MENU, self.OnDataDelete, id=wxID_DATADELETE)
125               
126    def _init_coll_Calculate_Items(self,parent):
127        self.UnDo = parent.Append(help='', id=wxID_UNDO, kind=wx.ITEM_NORMAL,
128            text='UnDo')
129        self.UnDo.Enable(False)
130        self.Bind(wx.EVT_MENU, self.OnUnDo, id=wxID_UNDO)
131       
132    def _init_coll_Import_Items(self,parent):
133        self.ImportPhase = parent.Append(help='Import phase data from GSAS EXP file',
134            id=wxID_IMPORTPHASE, kind=wx.ITEM_NORMAL,text='Import GSAS EXP Phase...')
135        self.ImportPDB = parent.Append(help='Import phase data from PDB file',
136            id=wxID_IMPORTPDB, kind=wx.ITEM_NORMAL,text='Import PDB Phase...')
137        self.ImportPattern = parent.Append(help='',id=wxID_IMPORTPATTERN, kind=wx.ITEM_NORMAL,
138            text='Import Powder Pattern...')
139        self.ImportHKL = parent.Append(help='',id=wxID_IMPORTHKL, kind=wx.ITEM_NORMAL,
140            text='Import HKLs...')
141        self.ImportCIF = parent.Append(help='',id=wxID_IMPORTCIF, kind=wx.ITEM_NORMAL,
142            text='Import CIF...')
143        self.Bind(wx.EVT_MENU, self.OnImportPhase, id=wxID_IMPORTPHASE)
144        self.Bind(wx.EVT_MENU, self.OnImportPDB, id=wxID_IMPORTPDB)
145        self.Bind(wx.EVT_MENU, self.OnImportPattern, id=wxID_IMPORTPATTERN)
146        self.Bind(wx.EVT_MENU, self.OnImportHKL, id=wxID_IMPORTHKL)
147        self.Bind(wx.EVT_MENU, self.OnImportCIF, id=wxID_IMPORTCIF)
148
149    def _init_coll_Export_Items(self,parent):
150        self.ExportPattern = parent.Append(help='Select PWDR item to enable',id=wxID_EXPORTPATTERN, kind=wx.ITEM_NORMAL,
151            text='Export Powder Pattern...')
152        self.ExportPeakList = parent.Append(help='',id=wxID_EXPORTPEAKLIST, kind=wx.ITEM_NORMAL,
153            text='Export All Peak Lists...')
154        self.ExportHKL = parent.Append(help='',id=wxID_EXPORTHKL, kind=wx.ITEM_NORMAL,
155            text='Export HKLs...')
156        self.ExportPhase = parent.Append(help='',id=wxID_EXPORTPHASE, kind=wx.ITEM_NORMAL,
157            text='Export Phase...')
158        self.ExportCIF = parent.Append(help='',id=wxID_EXPORTCIF, kind=wx.ITEM_NORMAL,
159            text='Export CIF...')
160        self.ExportPattern.Enable(False)
161        self.ExportPeakList.Enable(True)
162        self.ExportHKL.Enable(False)
163        self.ExportPhase.Enable(False)
164        self.ExportCIF.Enable(False)
165        self.Bind(wx.EVT_MENU, self.OnExportPattern, id=wxID_EXPORTPATTERN)
166        self.Bind(wx.EVT_MENU, self.OnExportPeakList, id=wxID_EXPORTPEAKLIST)
167        self.Bind(wx.EVT_MENU, self.OnExportHKL, id=wxID_EXPORTHKL)
168        self.Bind(wx.EVT_MENU, self.OnExportPhase, id=wxID_EXPORTPHASE)
169        self.Bind(wx.EVT_MENU, self.OnExportCIF, id=wxID_EXPORTCIF)
170               
171    def _init_coll_Help_Items(self, parent):
172        parent.Append(help='', id=wxID_HELPHELP, kind=wx.ITEM_NORMAL,
173            text='Help')
174        parent.Append(help='', id=wxID_HELPABOUT, kind=wx.ITEM_NORMAL,
175            text='About')
176        self.Bind(wx.EVT_MENU, self.OnHelpHelp, id=wxID_HELPHELP)
177        self.Bind(wx.EVT_MENU, self.OnHelpAbout, id=wxID_HELPABOUT)
178
179    def _init_utils(self):
180        self.GSASIIMenu = wx.MenuBar()
181        self.File = wx.Menu(title='')
182        self.Data = wx.Menu(title='')       
183        self.Calculate = wx.Menu(title='')       
184        self.Import = wx.Menu(title='')       
185        self.Export = wx.Menu(title='')       
186        self.Help = wx.Menu(title='')
187
188        self._init_coll_GSASIIMenu_Menus(self.GSASIIMenu)
189        self._init_coll_File_Items(self.File)
190        self._init_coll_Data_Items(self.Data)
191        self._init_coll_Calculate_Items(self.Calculate)
192        self._init_coll_Import_Items(self.Import)
193        self._init_coll_Export_Items(self.Export)
194        self._init_coll_Help_Items(self.Help)
195       
196    def _init_ctrls(self, parent):
197        wx.Frame.__init__(self, name='GSASII', parent=parent,
198            size=wx.Size(300, 250),style=wx.DEFAULT_FRAME_STYLE, title='GSAS-II data tree')
199        screenSize = wx.DisplaySize()
200        Size = self.GetSize()
201        xPos = screenSize[0]-Size[0]
202        self.SetPosition(wx.Point(xPos,0))
203        self._init_utils()
204        self.SetMenuBar(self.GSASIIMenu)
205        self.Bind(wx.EVT_SIZE, self.OnSize)
206        self.CreateStatusBar()
207        self.mainPanel = wx.Panel(self,-1)
208       
209        self.PatternTree = wx.TreeCtrl(id=wxID_PATTERNTREE,
210            parent=self.mainPanel, pos=wx.Point(0, 0),style=wx.TR_DEFAULT_STYLE )
211        self.PatternTree.Bind(wx.EVT_TREE_SEL_CHANGED,
212            self.OnPatternTreeSelChanged, id=wxID_PATTERNTREE)
213        self.PatternTree.Bind(wx.EVT_TREE_ITEM_COLLAPSED,
214            self.OnPatternTreeItemCollapsed, id=wxID_PATTERNTREE)
215        self.PatternTree.Bind(wx.EVT_TREE_ITEM_EXPANDED,
216            self.OnPatternTreeItemExpanded, id=wxID_PATTERNTREE)
217        self.root = self.PatternTree.AddRoot('Loaded Data: ')
218       
219        plotFrame = wx.Frame(None,-1,'GSASII Plots',size=wx.Size(700,600), \
220            style=wx.DEFAULT_FRAME_STYLE ^ wx.CLOSE_BOX)
221        self.G2plotNB = G2plt.G2PlotNoteBook(plotFrame)
222        plotFrame.Show()
223       
224        self.dataDisplay = None
225       
226    def __init__(self, parent):
227        self._init_ctrls(parent)
228        self.Bind(wx.EVT_CLOSE, self.ExitMain)
229        self.GSASprojectfile = ''
230        self.dirname = ''
231        self.undofile = ''
232        self.Offset = 0.0
233        self.Weight = False
234        self.IparmName = ''
235        self.IfPlot = False
236        self.PatternId = 0
237        self.PickId = 0
238        self.PeakTable = []
239        self.LimitsTable = []
240        self.HKL = []
241        self.Lines = []
242        self.itemPicked = None
243        self.dataFrame = None
244        self.Contour = False
245        self.SinglePlot = False
246        self.plotView = 0
247        self.Image = 0
248        self.oldImagefile = ''
249        self.Integrate = 0
250        self.Pwdr = False
251        self.imageDefault = {}
252        self.Sngl = 0
253        self.ifGetRing = False
254        self.setPoly = False
255        arg = sys.argv
256        if len(arg) > 1:
257            self.GSASprojectfile = arg[1]
258            self.dirname = ospath.dirname(arg[1])
259            G2IO.ProjFileOpen(self)
260            self.PatternTree.Expand(self.root)
261
262    def OnSize(self,event):
263        w,h = self.GetClientSizeTuple()
264        self.mainPanel.SetSize(wx.Size(w,h))
265        self.PatternTree.SetSize(wx.Size(w,h))
266                       
267    def OnPatternTreeSelChanged(self, event):
268        pltNum = self.G2plotNB.nb.GetSelection()
269        if pltNum >= 0:                         #to avoid the startup with no plot!
270            pltPage = self.G2plotNB.nb.GetPage(pltNum)
271            pltPlot = pltPage.figure
272        item = event.GetItem()
273        G2gd.MovePatternTreeToGrid(self,item)
274       
275    def OnPatternTreeItemCollapsed(self, event):
276        event.Skip()
277
278    def OnPatternTreeItemExpanded(self, event):
279        self.PatternTree.ScrollTo(self.PatternTree.GetLastChild(event.GetItem()))
280       
281    def OnPatternTreeDeleteItem(self, event):
282        event.Skip()
283
284    def OnPatternTreeItemActivated(self, event):
285        event.Skip()
286       
287    def OnPwdrRead(self, event):
288        self.CheckNotebook()
289        dlg = wx.FileDialog(self, 'Choose files', '.', '', 
290            'GSAS fxye files (*.fxye)|*.fxye|GSAS fxy files (*.fxy)|*.fxy|All files (*.*)|*.*', 
291            wx.OPEN | wx.MULTIPLE)
292        if self.dirname: dlg.SetDirectory(self.dirname)
293        try:
294            if dlg.ShowModal() == wx.ID_OK:
295                filenames = dlg.GetPaths()
296                filenames.sort()
297                self.dirname = dlg.GetDirectory()
298                for filename in filenames:
299                    Data,Iparm,Comments = G2IO.SelectPowderData(self, filename)              #Data: list of tuples (filename,Pos,Bank)
300                    if not Data:                                                    #if Data rejected by user - go to next one
301                        continue
302                    DataType = Iparm['INS   HTYPE ']                                #expect only 4 char string
303                    DataType = DataType.strip()[0:3]                                #just 1st 3 chars
304                    wx.BeginBusyCursor()
305                    Sample = {'Scale':[1.0,True],'Type':'Debye-Scherrer','Absorption':[0.0,False],'DisplaceX':[0.0,False],
306                        'DisplaceY':[0.0,False],'Diffuse':[]}
307                    try:
308                        for Item in Data:
309                            vals = Item[2].split()          #split up the BANK record
310                            Id = self.PatternTree.AppendItem(parent=self.root,text='PWDR '+ospath.basename(Item[0])+': '+vals[0]+vals[1])
311                            data = G2IO.GetPowderData(filename,Item[1],Item[2],DataType)
312                            self.PatternTree.SetItemPyData(Id,[Item,data])
313                            '''
314                            Each tree item data is a list with:
315                            Item: the (filename,Pos,Bank) tuple
316                            data: (x,y,w,yc,yb,yd) list  of np.arrays from GetPowderData
317                            '''
318                           
319                            self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Comments'),Comments)                           
320                            Tmin = min(data[0])
321                            Tmax = max(data[0])
322                            self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Limits'),[(Tmin,Tmax),[Tmin,Tmax]])
323                            self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Background'),[['chebyschev',1,3,1.0,0.0,0.0]])
324       
325                            data = [DataType,]
326                            if 'C' in DataType:
327                                s = Iparm['INS  1 ICONS']
328                                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
329                                if not v[1]:
330                                    names = ['Type','Lam','Zero','Polariz.','U','V','W','X','Y','SH/L','Azimuth'] 
331                                    v = (v[0],v[2],v[4])
332                                    codes = [0,0,0,0]
333                                else:
334                                    names = ['Type','Lam1','Lam2','Zero','I(L2)/I(L1)','Polariz.','U','V','W','X','Y','SH/L','Azimuth']
335                                    codes = [0,0,0,0,0,0]
336                                data.extend(v)
337                                v1 = Iparm['INS  1PRCF1 '].split()                                                 
338                                v = Iparm['INS  1PRCF11'].split()
339                                data.extend([float(v[0]),float(v[1]),float(v[2])])                  #get GU, GV & GW - always here
340                                v = Iparm['INS  1PRCF12'].split()
341                                if v1[0] == 3:
342                                    data.extend([float(v[0]),float(v[1]),float(v[2])+float(v[3],0.0)])  #get LX, LY, S+H/L & azimuth
343                                else:
344                                    data.extend([0.0,0.0,0.002,0.0])                                      #OK defaults if fxn #3 not 1st in iprm file
345                                codes.extend([0,0,0,0,0,0,0])
346                            self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Instrument Parameters'),[tuple(data),data,codes,names])
347                            self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Sample Parameters'),Sample)
348                            self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Peak List'),[])
349                            self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Index Peak List'),[])
350                            self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Unit Cells List'),[])             
351                            self.PatternId = G2gd.GetPatternTreeItemId(self,Id,'Limits')
352                    finally:
353                        wx.EndBusyCursor()
354                self.PatternTree.Expand(Id)
355                self.PatternTree.SelectItem(Id)
356   
357        finally:
358            dlg.Destroy()
359       
360    def OnReadPowderPeaks(self,event):
361        Cuka = 1.54052
362        self.CheckNotebook()
363        dlg = wx.FileDialog(self, 'Choose file with peak list', '.', '', 
364            'peak files (*.txt)|*.txt|All files (*.*)|*.*',wx.OPEN)
365        if self.dirname:
366            dlg.SetDirectory(self.dirname)
367        try:
368            if dlg.ShowModal() == wx.ID_OK:
369                self.HKL = []
370                self.powderfile = dlg.GetPath()
371                self.dirname = dlg.GetDirectory()
372                comments,peaks = G2IO.GetPowderPeaks(self.powderfile)
373                Id = self.PatternTree.AppendItem(parent=self.root,text='PKS '+ospath.basename(self.powderfile))
374                data = ['PKS',Cuka,0.0]
375                names = ['Type','Lam','Zero'] 
376                codes = [0,0]
377                self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Instrument Parameters'),[tuple(data),data,codes,names])
378                self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Comments'),comments)
379                self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Index Peak List'),peaks)
380                self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Unit Cells List'),[])             
381                self.PatternTree.Expand(Id)
382                self.PatternTree.SelectItem(Id)
383        finally:
384            dlg.Destroy()
385           
386    def OnImageRead(self,event):
387        self.CheckNotebook()
388        dlg = wx.FileDialog(self, 'Choose image files', '.', '',\
389        'MAR345 (*.mar3450;*.mar2300)|*.mar3450;*.mar2300|ADSC Image (*.img)\
390        |*.img|Detector tif (*.tif;*.tiff)|*.tif;*.tiff|GE Image sum (*.sum)\
391        |*.sum|GE Image avg (*.avg)|*.avg|All files (*.*)|*.*',wx.OPEN | wx.MULTIPLE)
392        if self.dirname:
393            dlg.SetDirectory(self.dirname)
394        try:
395            if dlg.ShowModal() == wx.ID_OK:
396                self.dirname = dlg.GetDirectory()
397                imagefiles = dlg.GetPaths()
398                imagefiles.sort()
399                for imagefile in imagefiles:
400                    Comments,Data,Size,Image = G2IO.GetImageData(imagefile)
401                    if Comments:
402                        Id = self.PatternTree.AppendItem(parent=self.root,text='IMG '+ospath.basename(imagefile))
403                        self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Comments'),Comments)
404                        Imax = np.amax(Image)
405                        Imin = np.amin(Image)
406                        if self.imageDefault:
407                            Data = copy.copy(self.imageDefault)
408                            Data['showLines'] = True
409                            Data['ring'] = []
410                            Data['rings'] = []
411                            Data['cutoff'] = 10
412                            Data['pixLimit'] = 20
413                            Data['ellipses'] = []
414                            Data['calibrant'] = ''
415                        else:
416                            Data['color'] = 'binary'
417                            Data['tilt'] = 0.0
418                            Data['rotation'] = 0.0
419                            Data['showLines'] = False
420                            Data['ring'] = []
421                            Data['rings'] = []
422                            Data['cutoff'] = 10
423                            Data['pixLimit'] = 20
424                            Data['ellipses'] = []
425                            Data['calibrant'] = ''
426                            Data['IOtth'] = [2.0,5.0]
427                            Data['LRazimuth'] = [-135,-45]
428                            Data['outChannels'] = 2500
429                            Data['outAzimuths'] = 1
430                            Data['fullIntegrate'] = False
431                            Data['setRings'] = False
432                        Data['setDefault'] = False
433                        Data['range'] = [(Imin,Imax),[Imin,Imax]]
434                        self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Image Controls'),Data)
435                        Masks = {'Points':[],'Rings':[],'Arcs':[],'Polygons':[],'Thresholds':[(Imin,Imax),[Imin,Imax]]}
436                        self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Masks'),Masks)
437                        self.PatternTree.SetItemPyData(Id,[Size,imagefile])
438                        self.PickId = Id
439                        self.Image = Id
440                self.PatternTree.SelectItem(Id)             #show last one
441                self.PatternTree.Expand(Id)
442        finally:
443            dlg.Destroy()
444       
445    def OnSnglRead(self,event):
446        self.CheckNotebook()
447        dlg = wx.FileDialog(self, 'Choose file', '.', '', 
448            'hkl files (*.hkl)|*.hkl|All files (*.*)|*.*', 
449            wx.OPEN)
450        if self.dirname: dlg.SetDirectory(self.dirname)
451        try:
452            if dlg.ShowModal() == wx.ID_OK:
453                filename = dlg.GetPath()
454                self.dirname = dlg.GetDirectory()
455                wx.BeginBusyCursor()
456                try:
457                    Data = {}
458                    names = ['Type','Lam']
459                    HKLref,HKLmin,HKLmax,FoMax,ifFc = G2IO.GetHKLData(filename)
460                    Id = self.PatternTree.AppendItem(parent=self.root,text='HKLF '+ospath.basename(filename))
461                    self.PatternTree.SetItemPyData(Id,HKLref)
462                    Sub = self.PatternTree.AppendItem(Id,text='Instrument Parameters')
463                    data = ['SXC',1.5428,]
464                    self.PatternTree.SetItemPyData(Sub,[tuple(data),data,names])
465                    Data['Type'] = 'Fosq'
466                    Data['ifFc'] = ifFc
467                    Data['HKLmax'] = HKLmax
468                    Data['HKLmin'] = HKLmin
469                    Data['FoMax'] = FoMax
470                    Data['Zone'] = '001'
471                    Data['Layer'] = 0
472                    Data['Scale'] = 1.0
473                    Data['log-lin'] = 'lin'                   
474                    self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='HKL Plot Controls'),Data)
475                    self.PatternTree.SelectItem(Id)
476                    self.PatternTree.Expand(Id)
477                    self.Sngl = Id
478                finally:
479                    wx.EndBusyCursor()   
480        finally:
481            dlg.Destroy()
482           
483    def CheckNotebook(self):
484        if not G2gd.GetPatternTreeItemId(self,self.root,'Notebook'):
485            sub = self.PatternTree.AppendItem(parent=self.root,text='Notebook')
486            self.PatternTree.SetItemPyData(sub,[''])
487            sub = self.PatternTree.AppendItem(parent=self.root,text='Controls')
488            self.PatternTree.SetItemPyData(sub,[0])
489               
490    class CopyDialog(wx.Dialog):
491        def __init__(self,parent,title,text,data):
492            wx.Dialog.__init__(self,parent,-1,title, 
493                pos=wx.DefaultPosition,style=wx.DEFAULT_DIALOG_STYLE)
494            self.data = data
495            panel = wx.Panel(self)
496            mainSizer = wx.BoxSizer(wx.VERTICAL)
497            topLabl = wx.StaticText(panel,-1,text)
498            mainSizer.Add((10,10),1)
499            mainSizer.Add(topLabl,0,wx.ALIGN_CENTER_VERTICAL|wx.LEFT,10)
500            mainSizer.Add((10,10),1)
501            dataGridSizer = wx.FlexGridSizer(rows=len(data),cols=1,hgap=2,vgap=2)
502            for id,item in enumerate(self.data):
503                ckbox = wx.CheckBox(panel,id,item[1])
504                ckbox.Bind(wx.EVT_CHECKBOX,self.OnCopyChange)                   
505                dataGridSizer.Add(ckbox,0,wx.LEFT,10)
506            mainSizer.Add(dataGridSizer,0,wx.EXPAND)
507            OkBtn = wx.Button(panel,-1,"Ok")
508            OkBtn.Bind(wx.EVT_BUTTON, self.OnOk)
509            cancelBtn = wx.Button(panel,-1,"Cancel")
510            cancelBtn.Bind(wx.EVT_BUTTON, self.OnCancel)
511            btnSizer = wx.BoxSizer(wx.HORIZONTAL)
512            btnSizer.Add((20,20),1)
513            btnSizer.Add(OkBtn)
514            btnSizer.Add((20,20),1)
515            btnSizer.Add(cancelBtn)
516            btnSizer.Add((20,20),1)
517           
518            mainSizer.Add(btnSizer,0,wx.EXPAND|wx.BOTTOM|wx.TOP, 10)
519            panel.SetSizer(mainSizer)
520            panel.Fit()
521            self.Fit()
522       
523        def OnCopyChange(self,event):
524            id = event.GetId()
525            self.data[id][0] = self.FindWindowById(id).GetValue()       
526           
527        def OnOk(self,event):
528            parent = self.GetParent()
529            parent.Raise()
530            self.EndModal(wx.ID_OK)             
531            self.Destroy()
532           
533        def OnCancel(self,event):
534            parent = self.GetParent()
535            parent.Raise()
536            self.EndModal(wx.ID_CANCEL)             
537            self.Destroy()
538           
539        def GetData(self):
540                return self.data
541       
542    class SumDialog(wx.Dialog):
543        def __init__(self,parent,title,text,dataType,data):
544            wx.Dialog.__init__(self,parent,-1,title, 
545                pos=wx.DefaultPosition,style=wx.DEFAULT_DIALOG_STYLE)
546            self.data = data
547            panel = wx.Panel(self)
548            mainSizer = wx.BoxSizer(wx.VERTICAL)
549            topLabl = wx.StaticText(panel,-1,text)
550            mainSizer.Add((10,10),1)
551            mainSizer.Add(topLabl,0,wx.ALIGN_CENTER_VERTICAL|wx.LEFT,10)
552            mainSizer.Add((10,10),1)
553            dataGridSizer = wx.FlexGridSizer(rows=len(data),cols=2,hgap=2,vgap=2)
554            for id,item in enumerate(self.data[:-1]):
555                name = wx.TextCtrl(panel,-1,item[1],size=wx.Size(200,20))
556                name.SetEditable(False)
557                scale = wx.TextCtrl(panel,id,str(item[0]),style=wx.TE_PROCESS_ENTER)
558                scale.Bind(wx.EVT_TEXT,self.OnScaleChange)                   
559                dataGridSizer.Add(scale,0,wx.LEFT,10)
560                dataGridSizer.Add(name,0,wx.RIGHT,10)
561            dataGridSizer.Add(wx.StaticText(panel,-1,'Sum result name: '+dataType),0, \
562                wx.LEFT|wx.TOP|wx.ALIGN_CENTER_VERTICAL,10)
563            self.name = wx.TextCtrl(panel,-1,self.data[-1],size=wx.Size(200,20),style=wx.TE_PROCESS_ENTER)
564            self.name.Bind(wx.EVT_TEXT,self.OnNameChange)
565            dataGridSizer.Add(self.name,0,wx.RIGHT|wx.TOP,10)
566            mainSizer.Add(dataGridSizer,0,wx.EXPAND)
567            OkBtn = wx.Button(panel,-1,"Ok")
568            OkBtn.Bind(wx.EVT_BUTTON, self.OnOk)
569            cancelBtn = wx.Button(panel,-1,"Cancel")
570            cancelBtn.Bind(wx.EVT_BUTTON, self.OnCancel)
571            btnSizer = wx.BoxSizer(wx.HORIZONTAL)
572            btnSizer.Add((20,20),1)
573            btnSizer.Add(OkBtn)
574            btnSizer.Add((20,20),1)
575            btnSizer.Add(cancelBtn)
576            btnSizer.Add((20,20),1)
577           
578            mainSizer.Add(btnSizer,0,wx.EXPAND|wx.BOTTOM|wx.TOP, 10)
579            panel.SetSizer(mainSizer)
580            panel.Fit()
581            self.Fit()
582           
583        def OnNameChange(self,event):
584            self.data[-1] = self.name.GetValue() 
585           
586        def OnScaleChange(self,event):
587            id = event.GetId()
588            value = self.FindWindowById(id).GetValue()
589            try:
590                self.data[id][0] = float(value)
591                self.FindWindowById(id).SetValue('%.3f'%(self.data[id][0]))
592            except ValueError:
593                if value and '-' not in value[0]:
594                    print 'bad input - numbers only'
595                    self.FindWindowById(id).SetValue('0.0')
596           
597        def OnOk(self,event):
598            parent = self.GetParent()
599            parent.Raise()
600            self.EndModal(wx.ID_OK)             
601            self.Destroy()
602           
603        def OnCancel(self,event):
604            parent = self.GetParent()
605            parent.Raise()
606            self.EndModal(wx.ID_CANCEL)             
607            self.Destroy()
608           
609        def GetData(self):
610            return self.data
611           
612    def OnPwdrSum(self,event):
613        TextList = []
614        DataList = []
615        SumList = []
616        Names = []
617        Inst = []
618        SumItemList = []
619        Comments = ['Sum equals: \n']
620        if self.PatternTree.GetCount():
621            item, cookie = self.PatternTree.GetFirstChild(self.root)
622            while item:
623                name = self.PatternTree.GetItemText(item)
624                Names.append(name)
625                if 'PWDR' in name:
626                    TextList.append([0.0,name])
627                    DataList.append(self.PatternTree.GetItemPyData(item)[1])    # (x,y,w,yc,yb,yd)
628                    if not Inst:
629                        Inst = self.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(self,item, 'Instrument Parameters'))
630                item, cookie = self.PatternTree.GetNextChild(self.root, cookie)
631            if len(TextList) < 2:
632                self.ErrorDialog('Not enough data to sum','There must be more than one "PWDR" pattern')
633                return
634            TextList.append('default_sum_name')               
635            dlg = self.SumDialog(self,'Sum data','Enter scale for each pattern in summation','PWDR',TextList)
636            try:
637                if dlg.ShowModal() == wx.ID_OK:
638                    lenX = 0
639                    Xminmax = [0,0]
640                    Xsum = []
641                    Ysum = []
642                    Wsum = []
643                    result = dlg.GetData()
644                    for i,item in enumerate(result[:-1]):
645                        scale,name = item
646                        data = DataList[i]
647                        if scale:
648                            Comments.append("%10.3f %s" % (scale,' * '+name))
649                            x,y,w,yc,yb,yd = data
650                            if lenX:
651                                if lenX != len(x):
652                                    self.ErrorDialog('Data length error','Data to be summed must have same number of points'+ \
653                                        '\nExpected:'+str(lenX)+ \
654                                        '\nFound:   '+str(len(x))+'\nfor '+name)
655                                    return
656                            else:
657                                lenX = len(x)
658                            if Xminmax[1]:
659                                if Xminmax != [x[0],x[-1]]:
660                                    self.ErrorDialog('Data range error','Data to be summed must span same range'+ \
661                                        '\nExpected:'+str(Xminmax[0])+' '+str(Xminmax[1])+ \
662                                        '\nFound:   '+str(x[0])+' '+str(x[-1])+'\nfor '+name)
663                                    return
664                                else:
665                                    for j,yi in enumerate(y):
666                                         Ysum[j] += scale*yi
667                            else:
668                                Xminmax = [x[0],x[-1]]
669                                YCsum = YBsum = YDsum = [0.0 for i in range(lenX)]
670                                for j,yi in enumerate(y):
671                                    Xsum.append(x[j])
672                                    Ysum.append(scale*yi)
673                                    Wsum.append(w[j])
674                    outname = 'PWDR '+result[-1]
675                    Id = 0
676                    if outname in Names:
677                        dlg2 = wx.MessageDialog(self,'Overwrite data?','Duplicate data name',wx.OK|wx.CANCEL)
678                        try:
679                            if dlg2.ShowModal() == wx.ID_OK:
680                                Id = G2gd.GetPatternTreeItemId(self,self.root,name)
681                        finally:
682                            dlg2.Destroy()
683                    else:
684                        Id = self.PatternTree.AppendItem(parent=self.root,text=outname)
685                    if Id:
686                        Sample = {'Scale':[1.0,True],'Type':'Debye-Scherrer','Absorption':[0.0,False],'DisplaceX':[0.0,False],
687                            'DisplaceY':[0.0,False],'Diffuse':[]}
688                        self.PatternTree.SetItemPyData(Id,[[''],[Xsum,Ysum,Wsum,YCsum,YBsum,YDsum]])
689                        self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Comments'),Comments)                   
690                        self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Limits'),[tuple(Xminmax),Xminmax])
691                        self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Background'),[['chebyschev',1,3,1.0,0.0,0.0]])
692                        self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Instrument Parameters'),Inst)
693                        self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Sample Parameters'),Sample)
694                        self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Peak List'),[])
695                        self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Index Peak List'),[])
696                        self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Unit Cells List'),[])             
697                        self.PatternTree.SelectItem(Id)
698                        self.PatternTree.Expand(Id)
699                   
700            finally:
701                dlg.Destroy()
702
703    def OnImageSum(self,event):
704        TextList = []
705        DataList = []
706        SumList = []
707        Names = []
708        Inst = []
709        SumItemList = []
710        Comments = ['Sum equals: \n']
711        if self.PatternTree.GetCount():
712            item, cookie = self.PatternTree.GetFirstChild(self.root)
713            while item:
714                name = self.PatternTree.GetItemText(item)
715                Names.append(name)
716                if 'IMG' in name:
717                    TextList.append([0.0,name])
718                    DataList.append(self.PatternTree.GetItemPyData(item))        #Size,Image
719                    Data = self.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(self,item,'Image Controls'))
720                item, cookie = self.PatternTree.GetNextChild(self.root, cookie)
721            if len(TextList) < 2:
722                self.ErrorDialog('Not enough data to sum','There must be more than one "IMG" pattern')
723                return
724            TextList.append('default_sum_name')               
725            dlg = self.SumDialog(self,'Sum data','Enter scale for each image in summation','IMG',TextList)
726            try:
727                if dlg.ShowModal() == wx.ID_OK:
728                    imSize = 0
729                    result = dlg.GetData()
730                    First = True
731                    Found = False
732                    for i,item in enumerate(result[:-1]):
733                        scale,name = item
734                        data = DataList[i]
735                        if scale:
736                            Found = True                               
737                            Comments.append("%10.3f %s" % (scale,' * '+name))
738                            size,imagefile = data
739                            image = G2IO.GetImageData(imagefile,imageOnly=True)
740                            if First:
741                                newImage = np.zeros_like(image)
742                                First = False
743                            if imSize:
744                                if imSize != size:
745                                    self.ErrorDialog('Image size error','Images to be summed must be same size'+ \
746                                        '\nExpected:'+str(imSize)+ \
747                                        '\nFound:   '+str(size)+'\nfor '+name)
748                                    return
749                                newImage = newImage+scale*image
750                            else:
751                                imSize = size
752                                newImage = newImage+scale*image
753                            del(image)
754                    if not Found:
755                        self.ErrorDialog('Image sum error','No nonzero image multipliers found')
756                        return
757                       
758                    newImage = np.asfarray(newImage,dtype=np.float32)                       
759                    outname = 'IMG '+result[-1]
760                    Id = 0
761                    if outname in Names:
762                        dlg2 = wx.MessageDialog(self,'Overwrite data?','Duplicate data name',wx.OK|wx.CANCEL)
763                        try:
764                            if dlg2.ShowModal() == wx.ID_OK:
765                                Id = G2gd.GetPatternTreeItemId(self,self.root,name)
766                        finally:
767                            dlg2.Destroy()
768                    else:
769                        Id = self.PatternTree.AppendItem(parent=self.root,text=outname)
770                    if Id:
771                        dlg = wx.FileDialog(self, 'Choose sum image filename', '.', '', 
772                            'G2img files (*.G2img)|*.G2img', 
773                            wx.SAVE|wx.FD_OVERWRITE_PROMPT)
774                        if self.dirname: dlg.SetDirectory(self.dirname)
775                        if dlg.ShowModal() == wx.ID_OK:
776                            self.dirname = dlg.GetDirectory()
777                            newimagefile = dlg.GetPath()
778                            G2IO.PutG2Image(newimagefile,newImage)
779                            Imax = np.amax(newImage)
780                            Imin = np.amin(newImage)
781                            newImage = []
782                            self.PatternTree.SetItemPyData(Id,[imSize,newimagefile])
783                            self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Comments'),Comments)
784                        del(newImage)
785                        if self.imageDefault:
786                            Data = copy.copy(self.imageDefault)
787                        Data['showLines'] = True
788                        Data['ring'] = []
789                        Data['rings'] = []
790                        Data['cutoff'] = 10
791                        Data['pixLimit'] = 20
792                        Data['ellipses'] = []
793                        Data['calibrant'] = ''
794                        Data['range'] = [(Imin,Imax),[Imin,Imax]]
795                        self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Image Controls'),Data)                                           
796                        Masks = {'Points':[],'Rings':[],'Arcs':[],'Polygons':[],'Thresholds':[(Imin,Imax),[Imin,Imax]]}
797                        self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Masks'),Masks)
798                        self.PatternTree.SelectItem(Id)
799                        self.PatternTree.Expand(Id)
800                        self.PickId = G2gd.GetPatternTreeItemId(self,self.root,outname)
801                        self.Image = self.PickId
802            finally:
803                dlg.Destroy()
804                     
805    def OnAddPhase(self,event):
806        if not G2gd.GetPatternTreeItemId(self,self.root,'Phases'):
807            sub = self.PatternTree.AppendItem(parent=self.root,text='Phases')
808        else:
809            sub = G2gd.GetPatternTreeItemId(self,self.root,'Phases')
810        PhaseName = ''
811        dlg = wx.TextEntryDialog(None,'Enter a name for this phase','Phase Name Entry','New phase',
812            style=wx.OK)
813        if dlg.ShowModal() == wx.ID_OK:
814            PhaseName = dlg.GetValue()
815        dlg.Destroy()
816        sub = self.PatternTree.AppendItem(parent=sub,text=PhaseName)
817        E,SGData = G2spc.SpcGroup('P 1')
818        self.PatternTree.SetItemPyData(sub, \
819            {'General':{'Name':PhaseName,'Type':'nuclear','SGData':SGData,
820            'Cell':[False,10.,10.,10.,90.,90.,90,1000.],
821            'Pawley dmin':1.0},'Atoms':[],'Drawing':{},'Histograms':{}})
822       
823    def OnDeletePhase(self,event):
824        if self.dataFrame:
825            self.dataFrame.Clear() 
826        TextList = []
827        DelList = []
828        DelItemList = []
829        if G2gd.GetPatternTreeItemId(self,self.root,'Phases'):
830            sub = G2gd.GetPatternTreeItemId(self,self.root,'Phases')
831        else:
832            return
833        if sub:
834            item, cookie = self.PatternTree.GetFirstChild(sub)
835            while item:
836                TextList.append(self.PatternTree.GetItemText(item))
837                item, cookie = self.PatternTree.GetNextChild(sub, cookie)               
838            dlg = wx.MultiChoiceDialog(self, 'Which phase to delete?', 'Delete phase', TextList, wx.CHOICEDLG_STYLE)
839            try:
840                if dlg.ShowModal() == wx.ID_OK:
841                    result = dlg.GetSelections()
842                    for i in result: DelList.append([i,TextList[i]])
843                    item, cookie = self.PatternTree.GetFirstChild(sub)
844                    i = 0
845                    while item:
846                        if [i,self.PatternTree.GetItemText(item)] in DelList: DelItemList.append(item)
847                        item, cookie = self.PatternTree.GetNextChild(sub, cookie)
848                        i += 1
849                    for item in DelItemList:
850                        name = self.PatternTree.GetItemText(item)
851                        self.PatternTree.Delete(item)
852                        self.G2plotNB.Delete(name)
853            finally:
854                dlg.Destroy()
855               
856    def OnRenameData(self,event):
857        name = self.PatternTree.GetItemText(self.PickId)     
858        if 'PWDR' in name or 'HKLF' in name or 'IMG' in name:
859            dataType = name[:name.index(' ')+1]                 #includes the ' '
860            dlg = wx.TextEntryDialog(self,'Data name: '+dataType,'Change data name',
861                defaultValue=name[name.index(' ')+1:])
862            try:
863                if dlg.ShowModal() == wx.ID_OK:
864                    self.PatternTree.SetItemText(self.PickId,dataType+dlg.GetValue())
865            finally:
866                dlg.Destroy()
867       
868    def OnDataDelete(self, event):
869        TextList = []
870        DelList = []
871        DelItemList = []
872        if self.PatternTree.GetCount():
873            item, cookie = self.PatternTree.GetFirstChild(self.root)
874            while item:
875                name = self.PatternTree.GetItemText(item)
876                if 'PWDR' in name or 'HKLF' in name or 'IMG' in name:
877                    TextList.append(name)
878                item, cookie = self.PatternTree.GetNextChild(self.root, cookie)               
879            dlg = wx.MultiChoiceDialog(self, 'Which data to delete?', 'Delete data', TextList, wx.CHOICEDLG_STYLE)
880            try:
881                if dlg.ShowModal() == wx.ID_OK:
882                    result = dlg.GetSelections()
883                    for i in result: DelList.append(TextList[i])
884                    item, cookie = self.PatternTree.GetFirstChild(self.root)
885                    while item:
886                        if self.PatternTree.GetItemText(item) in DelList: DelItemList.append(item)
887                        item, cookie = self.PatternTree.GetNextChild(self.root, cookie)
888                    for item in DelItemList:
889                        self.PatternTree.Delete(item)
890                    G2plt.PlotPatterns(self,True)                        #so plot gets updated
891            finally:
892                dlg.Destroy()
893
894    def OnFileOpen(self, event):
895        result = ''
896        Id = 0
897        if self.PatternTree.GetChildrenCount(self.root,False):
898            if self.dataFrame:
899                self.dataFrame.Clear() 
900            dlg = wx.MessageDialog(self, 'Overwrite?','Project exists!',  wx.OK | wx.CANCEL)
901            try:
902                result = dlg.ShowModal()
903                if result == wx.ID_OK:
904                    self.PatternTree.DeleteChildren(self.root)
905                    self.GSASprojectfile = ''
906                    self.PatternTree.DeleteChildren(self.root)
907                    if self.HKL: self.HKL = []
908                    if self.G2plotNB.plotList:
909                        self.G2plotNB.clear()
910            finally:
911                dlg.Destroy()
912        if result != wx.ID_CANCEL:   
913            if self.dataDisplay: self.dataDisplay.Destroy()
914            dlg = wx.FileDialog(self, 'Choose GSAS-II project file', '.', '', 
915                'GSAS-II project file (*.gpx)|*.gpx',wx.OPEN)
916            if self.dirname: dlg.SetDirectory(self.dirname)
917            try:
918                if dlg.ShowModal() == wx.ID_OK:
919                    self.GSASprojectfile = dlg.GetPath()
920                    self.dirname = dlg.GetDirectory()
921                    G2IO.ProjFileOpen(self)
922                    self.PatternTree.SetItemText(self.root,'Loaded Data: '+self.GSASprojectfile)
923                    self.PatternTree.Expand(self.root)
924                    self.HKL = []
925                    item, cookie = self.PatternTree.GetFirstChild(self.root)
926                    while item and not Id:
927                        name = self.PatternTree.GetItemText(item)
928                        if 'PWDR' in name or 'HKLF' in name or 'IMG' in name:
929                            Id = item
930                        item, cookie = self.PatternTree.GetNextChild(self.root, cookie)               
931                    if Id:
932                        self.PatternTree.SelectItem(Id)
933            finally:
934                dlg.Destroy()
935
936    def OnFileClose(self, event):
937        if self.dataFrame:
938            self.dataFrame.Clear()
939            self.dataFrame.SetLabel('GSAS-II data display') 
940        dlg = wx.MessageDialog(self, 'Save current project?', ' ', wx.YES | wx.NO | wx.CANCEL)
941        try:
942            result = dlg.ShowModal()
943            if result == wx.ID_OK:
944                self.OnFileSaveMenu(event)
945            if result != wx.ID_CANCEL:
946                self.GSASprojectfile = ''
947                self.PatternTree.SetItemText(self.root,'Loaded Data: ')
948                self.PatternTree.DeleteChildren(self.root)
949                if self.HKL: self.HKL = []
950                if self.G2plotNB.plotList:
951                    self.G2plotNB.clear()
952        finally:
953            dlg.Destroy()
954
955    def OnFileSave(self, event):
956        if self.GSASprojectfile: 
957            self.PatternTree.SetItemText(self.root,'Loaded Data: '+self.GSASprojectfile)
958            G2IO.ProjFileSave(self)
959        else:
960            self.OnFileSaveas(event)
961
962    def OnFileSaveas(self, event):
963        dlg = wx.FileDialog(self, 'Choose GSAS-II project file name', '.', '', 
964            'GSAS-II project file (*.gpx)|*.gpx',wx.FD_SAVE|wx.FD_OVERWRITE_PROMPT)
965        if self.dirname:
966            dlg.SetDirectory(self.dirname)
967        try:
968            if dlg.ShowModal() == wx.ID_OK:
969                self.GSASprojectfile = dlg.GetPath()
970                self.PatternTree.SetItemText(self.root,'Loaded Data: '+self.GSASprojectfile)
971                G2IO.ProjFileSave(self)
972                self.dirname = dlg.GetDirectory()
973        finally:
974            dlg.Destroy()
975
976    def ExitMain(self, event):
977        if self.undofile:
978            os.remove(self.undofile)
979        sys.exit()
980       
981    def OnFileExit(self, event):
982        if self.dataFrame:
983            self.dataFrame.Clear() 
984            self.dataFrame.Destroy()
985        self.Close()
986       
987    def OnImportPattern(self,event):
988            dlg = wx.FileDialog(self, 'Choose nonGSAS powder file', '.', '', 
989                '(*.*)|*.*',wx.OPEN)
990            if self.dirname:
991                dlg.SetDirectory(self.dirname)
992            try:
993                if dlg.ShowModal() == wx.ID_OK:
994                    self.powderfile = dlg.GetPath()
995                    self.dirname = dlg.GetDirectory()
996            finally:
997                dlg.Destroy()
998               
999    def OnImportHKL(self,event):
1000            dlg = wx.FileDialog(self, 'Choose structure factor file', '.', '', 
1001                '(*.*)|*.*',wx.OPEN)
1002            if self.dirname:
1003                dlg.SetDirectory(self.dirname)
1004            try:
1005                if dlg.ShowModal() == wx.ID_OK:
1006                    self.HKLfile = dlg.GetPath()
1007                    self.dirname = dlg.GetDirectory()
1008            finally:
1009                dlg.Destroy()
1010       
1011    def OnImportPhase(self,event):
1012            dlg = wx.FileDialog(self, 'Choose GSAS EXP file', '.', '', 
1013                'EXP file (*.EXP)|*.EXP',wx.OPEN)
1014            if self.dirname:
1015                dlg.SetDirectory(self.dirname)
1016            try:
1017                Phase = {}
1018                if dlg.ShowModal() == wx.ID_OK:
1019                    EXPfile = dlg.GetPath()
1020                    self.dirname = dlg.GetDirectory()
1021                    Phase = G2IO.ReadEXPPhase(self,EXPfile)
1022            finally:
1023                dlg.Destroy()
1024            if Phase:
1025                PhaseName = Phase['General']['Name']
1026                if not G2gd.GetPatternTreeItemId(self,self.root,'Phases'):
1027                    sub = self.PatternTree.AppendItem(parent=self.root,text='Phases')
1028                else:
1029                    sub = G2gd.GetPatternTreeItemId(self,self.root,'Phases')
1030                sub = self.PatternTree.AppendItem(parent=sub,text=PhaseName)
1031                self.PatternTree.SetItemPyData(sub,Phase)
1032               
1033    def OnImportPDB(self,event):
1034            dlg = wx.FileDialog(self, 'Choose PDB file', '.', '', 
1035                'PDB file (*.pdb,*.ent)|*.pdb;*.ent|All files (*.*)|*.*',wx.OPEN)
1036            if self.dirname:
1037                dlg.SetDirectory(self.dirname)
1038            try:
1039                if dlg.ShowModal() == wx.ID_OK:
1040                    PDBfile = dlg.GetPath()
1041                    self.dirname = dlg.GetDirectory()
1042                    Phase = G2IO.ReadPDBPhase(PDBfile)
1043            finally:
1044                dlg.Destroy()
1045            if Phase:
1046                PhaseName = Phase['General']['Name']
1047                if not G2gd.GetPatternTreeItemId(self,self.root,'Phases'):
1048                    sub = self.PatternTree.AppendItem(parent=self.root,text='Phases')
1049                else:
1050                    sub = G2gd.GetPatternTreeItemId(self,self.root,'Phases')
1051                sub = self.PatternTree.AppendItem(parent=sub,text=PhaseName)
1052                self.PatternTree.SetItemPyData(sub,Phase)       
1053       
1054    def OnImportCIF(self,event):
1055            dlg = wx.FileDialog(self, 'Choose CIF file', '.', '', 
1056                'CIF file (*.cif)|*.cif',wx.OPEN)
1057            if self.dirname:
1058                dlg.SetDirectory(self.dirname)
1059            try:
1060                if dlg.ShowModal() == wx.ID_OK:
1061                    self.CIFfile = dlg.GetPath()
1062                    self.dirname = dlg.GetDirectory()
1063            finally:
1064                dlg.Destroy()
1065       
1066    def OnExportPattern(self,event):
1067        dlg = wx.FileDialog(self, 'Choose output powder file name', '.', '', 
1068            'GSAS fxye file (*.fxye)|*.fxye|xye file (*.xye)|*.xye',
1069            wx.FD_SAVE|wx.FD_OVERWRITE_PROMPT)
1070        if self.dirname:
1071            dlg.SetDirectory(self.dirname)
1072        try:
1073            if dlg.ShowModal() == wx.ID_OK:
1074                powderfile = dlg.GetPath()
1075                if 'fxye' in powderfile:
1076                    G2IO.powderFxyeSave(self,powderfile)
1077                else:       #just xye
1078                    G2IO.powderXyeSave(self,powderfile)
1079                self.dirname = dlg.GetDirectory()
1080        finally:
1081            dlg.Destroy()
1082       
1083    def OnExportPeakList(self,event):
1084        dlg = wx.FileDialog(self, 'Choose output peak list file name', '.', '', 
1085            '(*.*)|*.*',wx.FD_SAVE|wx.FD_OVERWRITE_PROMPT)
1086        if self.dirname:
1087            dlg.SetDirectory(self.dirname)
1088        try:
1089            if dlg.ShowModal() == wx.ID_OK:
1090                self.peaklistfile = dlg.GetPath()
1091                file = open(self.peaklistfile,'w')               
1092                item, cookie = self.PatternTree.GetFirstChild(self.root)
1093                while item:
1094                    name = self.PatternTree.GetItemText(item)
1095                    if 'PWDR' in name:
1096                        item2, cookie2 = self.PatternTree.GetFirstChild(item)
1097                        while item2:
1098                            name2 = self.PatternTree.GetItemText(item2)
1099                            if name2 == 'Peak List':
1100                                peaks = self.PatternTree.GetItemPyData(item2)
1101                                file.write("%s \n" % (name+' Peak List'))               
1102                                for peak in peaks:
1103                                    file.write("%10.4f %12.2f %10.3f %10.3f \n" % \
1104                                        (peak[0],peak[2],peak[4],peak[6]))
1105                            item2, cookie2 = self.PatternTree.GetNextChild(item, cookie2)                           
1106                    item, cookie = self.PatternTree.GetNextChild(self.root, cookie)                           
1107                file.close()
1108                self.dirname = dlg.GetDirectory()
1109        finally:
1110            dlg.Destroy()
1111       
1112    def OnExportHKL(self,event):
1113        event.Skip()
1114       
1115    def OnExportPhase(self,event):
1116        event.Skip()
1117       
1118    def OnExportCIF(self,event):
1119        event.Skip()
1120       
1121    def OnUnDo(self,event):
1122        self.DoUnDo()
1123        self.UnDo.Enable(False)
1124       
1125    def DoUnDo(self):
1126        print 'Undo last refinement'
1127        file = open(self.undofile,'rb')
1128        PatternId = self.PatternId
1129        for item in ['Background','Instrument Parameters','Peak List']:
1130            self.PatternTree.SetItemPyData(G2gd.GetPatternTreeItemId(self,PatternId, item),cPickle.load(file))
1131            if self.dataDisplay.GetName() == item:
1132                if item == 'Background':
1133                    G2pdG.UpdateBackgroundGrid(self,self.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(self,PatternId, item)))
1134                elif item == 'Instrument Parameters':
1135                    G2pdG.UpdateInstrumentGrid(self,self.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(self,PatternId, item)))
1136                elif item == 'Peak List':
1137                    G2pdG.UpdatePeakGrid(self,self.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(self,PatternId, item)))
1138            print item,' recovered'
1139        file.close()
1140       
1141    def SaveState(self):
1142        self.undofile = self.dirname+'\\GSASII.save'
1143        file = open(self.undofile,'wb')
1144        PatternId = self.PatternId
1145        for item in ['Background','Instrument Parameters','Peak List']:
1146            cPickle.dump(self.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(self,PatternId,item)),file,1)
1147        file.close()
1148        self.UnDo.Enable(True)
1149               
1150    def ErrorDialog(self,title,message):
1151        dlg = wx.MessageDialog(self, message, title,  wx.OK)
1152        try:
1153            result = dlg.ShowModal()
1154        finally:
1155            dlg.Destroy()
1156
1157    def OnHelpHelp(self, event):
1158        event.Skip()
1159       
1160    def OnHelpAbout(self, event):
1161        info = wx.AboutDialogInfo()
1162        info.Name = 'GSAS-II'
1163        info.Version = __version__
1164        info.Copyright = '''
1165Robert B. Von Dreele
1166Argonne National Laboratory(C)
1167This product includes software developed
1168by the UChicago Argonne, LLC, as
1169Operator of Argonne National Laboratory.         '''
1170        info.Description = '''
1171General Structure Analysis System - II
1172        '''
1173        wx.AboutBox(info)
1174       
1175class GSASIImain(wx.App):
1176    def OnInit(self):
1177        self.main = GSASII(None)
1178        self.main.Show()
1179        self.SetTopWindow(self.main)
1180        return True
1181
1182def main():
1183    application = GSASIImain(0)
1184    application.MainLoop()
1185
1186if __name__ == '__main__':
1187    main()
Note: See TracBrowser for help on using the repository browser.