source: trunk/GSASII.py @ 161

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

implement hardcopy (jpeg, tiff & bmp) output of structure drawings

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