source: trunk/GSASII.py @ 584

Last change on this file since 584 was 584, checked in by vondreele, 10 years ago

add coding line everywhere
more options in sample parm copy

  • Property svn:keywords set to Date Author Revision URL Id
File size: 88.1 KB
Line 
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3#GSASII
4########### SVN repository information ###################
5# $Date: 2012-05-03 16:35:40 +0000 (Thu, 03 May 2012) $
6# $Author: vondreele $
7# $Revision: 584 $
8# $URL: trunk/GSASII.py $
9# $Id: GSASII.py 584 2012-05-03 16:35:40Z vondreele $
10########### SVN repository information ###################
11
12import os
13import os.path as ospath
14import sys
15import math
16#import cPickle
17import time
18import copy
19import glob
20import imp
21import inspect
22import numpy as np
23import scipy as sp
24import wx
25import matplotlib as mpl
26import wx.lib.inspection as wxeye
27try:
28    import OpenGL as ogl
29except ImportError:
30    print('*******************************************************')
31    print('PyOpenGL is missing from your python installation')
32    print('     - we will try to install it')
33    print('*******************************************************')
34    def install_with_easyinstall(package):
35        try: 
36            print "trying a system-wide PyOpenGl install"
37            easy_install.main(['-f',ospath.split(__file__)[0],package])
38            return
39        except:
40            pass
41        try: 
42            print "trying a user level PyOpenGl install"
43            easy_install.main(['-f',ospath.split(__file__)[0],'--user',package])
44            return
45        except:
46            print "Install of '+package+' failed. Please report this information:"
47            import traceback
48            print traceback.format_exc()
49            sys.exit()
50    from setuptools.command import easy_install
51    install_with_easyinstall('PyOpenGl')
52    print('*******************************************************')         
53    print('OpenGL has been installed. Please restart GSAS-II')
54    print('*******************************************************')         
55    sys.exit()
56
57# load the GSAS routines
58import GSASIIpath
59import GSASIIIO as G2IO
60import GSASIIgrid as G2gd
61import GSASIIplot as G2plt
62import GSASIIpwdGUI as G2pdG
63import GSASIIspc as G2spc
64import GSASIIstruct as G2str
65import GSASIImapvars as G2mv
66import GSASIIsolve as G2sol
67
68#wx inspector - use as needed
69wxInspector = False
70
71# print versions
72print "Available python module versions for GSASII:"
73print "python:     ",sys.version[:5]
74print "wxpython:   ",wx.__version__
75print "matplotlib: ",mpl.__version__
76print "numpy:      ",np.__version__
77print "scipy:      ",sp.__version__
78print "OpenGL:     ",ogl.__version__
79try:
80    import mkl
81    print "Max threads ",mkl.get_max_threads()
82except:
83    print "MKL module not present"
84__version__ = '0.1.5'
85G2gd.__version__ = __version__
86print "This is GSAS-II version:     ",__version__
87
88# useful degree trig functions
89sind = lambda x: math.sin(x*math.pi/180.)
90cosd = lambda x: math.cos(x*math.pi/180.)
91tand = lambda x: math.tan(x*math.pi/180.)
92asind = lambda x: 180.*math.asin(x)/math.pi
93acosd = lambda x: 180.*math.acos(x)/math.pi
94atan2d = lambda x,y: 180.*math.atan2(y,x)/math.pi
95
96def create(parent):
97    return GSASII(parent)
98
99[wxID_PATTERNTREE, 
100] = [wx.NewId() for _init_ctrls in range(1)]
101
102[wxID_FILECLOSE, wxID_FILEEXIT, wxID_FILEOPEN,  wxID_FILESAVE, wxID_FILESAVEAS, 
103wxID_REFINE,  wxID_MAKEPDFS, wxID_VIEWLSPARMS, wxID_SEQREFINE,
104] = [wx.NewId() for _init_coll_File_Items in range(9)]
105
106[wxID_PWDRREAD,wxID_SNGLREAD,wxID_ADDPHASE,wxID_DELETEPHASE,
107 wxID_DATADELETE,wxID_READPEAKS,wxID_PWDSUM,wxID_IMGREAD,
108 wxID_IMSUM, wxID_DATARENAME,
109] = [wx.NewId() for _init_coll_Data_Items in range(10)]
110
111[wxID_IMPORT, wxID_IMPORTPATTERN, wxID_IMPORTHKL
112#, wxID_IMPORTPHASE,
113#wxID_IMPORTCIF, wxID_IMPORTPDB, 
114] = [wx.NewId() for _init_coll_Import_Items in range(3)]
115
116[wxID_EXPORT, wxID_EXPORTPATTERN, wxID_EXPORTHKL, wxID_EXPORTPHASE,
117wxID_EXPORTCIF, wxID_EXPORTPEAKLIST, wxID_EXPORTPDF,
118] = [wx.NewId() for _init_coll_Export_Items in range(7)]
119
120class GSASII(wx.Frame):
121   
122    def _init_coll_GSASIIMenu_Menus(self, parent):
123        parent.Append(menu=self.File, title='File')
124        parent.Append(menu=self.Data, title='Data')
125        parent.Append(menu=self.Calculate, title='Calculate')
126        parent.Append(menu=self.Import, title='Import')
127        parent.Append(menu=self.Export, title='Export')
128        parent.Append(menu=G2gd.MyHelp(self,helpType='Data tree'),title='&Help' )
129
130    def _init_coll_File_Items(self, parent):
131        parent.Append(help='Open a gsasii project file (*.gpx)', id=wxID_FILEOPEN,
132             kind=wx.ITEM_NORMAL,text='Open project...')
133        parent.Append(help='Save project to old file', id=wxID_FILESAVE, 
134            kind=wx.ITEM_NORMAL,text='Save project')
135        parent.Append(help='Save project to new file', id=wxID_FILESAVEAS, 
136            kind=wx.ITEM_NORMAL,text='Save As...')
137        parent.Append(help='Close project, saving is optional', id=wxID_FILECLOSE, 
138            kind=wx.ITEM_NORMAL,text='Close project')
139        parent.Append(help='Exit from gsasii', id=wxID_FILEEXIT, kind=wx.ITEM_NORMAL,
140            text='Exit')
141        self.Bind(wx.EVT_MENU, self.OnFileOpen, id=wxID_FILEOPEN)
142        self.Bind(wx.EVT_MENU, self.OnFileSave, id=wxID_FILESAVE)
143        self.Bind(wx.EVT_MENU, self.OnFileSaveas, id=wxID_FILESAVEAS)
144        self.Bind(wx.EVT_MENU, self.OnFileClose, id=wxID_FILECLOSE)
145        self.Bind(wx.EVT_MENU, self.OnFileExit, id=wxID_FILEEXIT)
146       
147    def _init_coll_Data_Items(self,parent):
148        parent.Append(help='', id=wxID_PWDRREAD, kind=wx.ITEM_NORMAL,
149            text='Read powder data...')
150        parent.Append(help='',id=wxID_IMGREAD, kind=wx.ITEM_NORMAL,
151            text='Read image data...')
152        parent.Append(help='',id=wxID_READPEAKS, kind=wx.ITEM_NORMAL,
153            text='Read Powder Pattern Peaks...')
154        parent.Append(help='', id=wxID_SNGLREAD, kind=wx.ITEM_NORMAL,
155            text='Read single crystal data...')
156        parent.Append(help='', id=wxID_PWDSUM, kind=wx.ITEM_NORMAL,
157            text='Sum powder data')
158        parent.Append(help='',id=wxID_IMSUM, kind=wx.ITEM_NORMAL,
159            text='Sum image data')
160        parent.Append(help='', id=wxID_ADDPHASE, kind=wx.ITEM_NORMAL,
161            text='Add phase')
162        parent.Append(help='', id=wxID_DELETEPHASE, kind=wx.ITEM_NORMAL,
163            text='Delete phase')
164        parent.Append(help='', id=wxID_DATARENAME, kind=wx.ITEM_NORMAL,
165            text='Rename data') 
166        parent.Append(help='', id=wxID_DATADELETE, kind=wx.ITEM_NORMAL,
167            text='Delete data')
168        self.Bind(wx.EVT_MENU, self.OnPwdrRead, id=wxID_PWDRREAD)
169        self.Bind(wx.EVT_MENU, self.OnPwdrSum, id=wxID_PWDSUM)
170        self.Bind(wx.EVT_MENU, self.OnReadPowderPeaks, id=wxID_READPEAKS)
171        self.Bind(wx.EVT_MENU, self.OnImageRead, id=wxID_IMGREAD)
172        self.Bind(wx.EVT_MENU, self.OnImageSum, id=wxID_IMSUM)
173        self.Bind(wx.EVT_MENU, self.OnSnglRead, id=wxID_SNGLREAD)
174        self.Bind(wx.EVT_MENU, self.OnAddPhase, id=wxID_ADDPHASE)
175        self.Bind(wx.EVT_MENU, self.OnDeletePhase, id=wxID_DELETEPHASE)
176        self.Bind(wx.EVT_MENU, self.OnRenameData, id=wxID_DATARENAME)
177        self.Bind(wx.EVT_MENU, self.OnDataDelete, id=wxID_DATADELETE)
178               
179    def _init_coll_Calculate_Items(self,parent):
180        self.MakePDF = parent.Append(help='Make new PDFs from selected powder patterns', 
181            id=wxID_MAKEPDFS, kind=wx.ITEM_NORMAL,text='Make new PDFs')
182        self.Bind(wx.EVT_MENU, self.OnMakePDFs, id=wxID_MAKEPDFS)
183        self.ViewLSParms = parent.Append(help='View least squares parameters', 
184            id=wxID_VIEWLSPARMS, kind=wx.ITEM_NORMAL,text='View LS parms')
185        self.Bind(wx.EVT_MENU, self.OnViewLSParms, id=wxID_VIEWLSPARMS)
186        self.Refine = parent.Append(help='', id=wxID_REFINE, kind=wx.ITEM_NORMAL,
187            text='Refine')
188        self.Refine.Enable(False)
189        self.Bind(wx.EVT_MENU, self.OnRefine, id=wxID_REFINE)
190        self.SeqRefine = parent.Append(help='', id=wxID_SEQREFINE, kind=wx.ITEM_NORMAL,
191            text='Sequental refine')
192        self.SeqRefine.Enable(False)
193        self.Bind(wx.EVT_MENU, self.OnSeqRefine, id=wxID_SEQREFINE)
194       
195    def _init_Import_routines(self,parent,prefix,readerlist,errprefix):
196        '''import all the import readers matching the prefix
197        '''
198        path2GSAS2 = os.path.dirname(os.path.realpath(__file__)) # location of this file
199        pathlist = sys.path[:]
200        if path2GSAS2 not in pathlist: pathlist.append(path2GSAS2)
201        filelist = []
202        for path in pathlist:
203            for filename in glob.iglob(os.path.join(
204                path,
205                "G2import"+prefix+"*.py")):
206                filelist.append(filename)   
207                #print 'found',filename
208        filelist = sorted(list(set(filelist))) # remove duplicates
209        for filename in filelist:
210            path,rootname = os.path.split(filename)
211            pkg = os.path.splitext(rootname)[0]
212            try:
213                fp = None
214                fp, fppath,desc = imp.find_module(pkg,[path,])
215                pkg = imp.load_module(pkg,fp,fppath,desc)
216                for clss in inspect.getmembers(pkg): # find classes defined in package
217                    if clss[0].startswith('_'): continue
218                    if inspect.isclass(clss[1]):
219                        # check if we have the required methods
220                        for m in 'Reader','ExtensionValidator','ContentsValidator':
221                            if not hasattr(clss[1],m): break
222                            if not callable(getattr(clss[1],m)): break
223                        else:
224                            reader = clss[1]() # create an import instance
225                            readerlist.append(reader)
226            except AttributeError:
227                print 'Import_'+errprefix+': Attribute Error'+str(filename)
228                pass
229            except ImportError:
230                print 'Import_'+errprefix+': Error importing file'+str(filename)
231                pass
232            finally:
233                if fp: fp.close()
234
235    def OnImportGeneric(self,reader,readerlist,label):
236        '''Call the requested import reader or all of the appropriate
237        import readers in response to a menu item
238        '''
239        self.lastimport = ''
240        if reader is None:
241            #print "use all formats"
242            choices = "any file (*.*)|*.*"
243            extdict = {}
244            # compile a list of allowed extensions
245            for rd in readerlist:
246                fmt = rd.formatName
247                for extn in rd.extensionlist:
248                    if not extdict.get(extn): extdict[extn] = []
249                    extdict[extn] += [fmt,]
250            for extn in sorted(extdict.keys(),cmp=lambda x,y: cmp(x.lower(), y.lower())):
251                fmt = ''
252                for f in extdict[extn]:
253                    if fmt != "": fmt += ', '
254                    fmt += f
255                choices += "|" + fmt + " file (*" + extn + ")|*" + extn
256        else:
257            readerlist = [reader,]
258            # compile a list of allowed extensions
259            choices = reader.formatName + " file ("
260            w = ""
261            for extn in reader.extensionlist:
262                if w != "": w += ";"
263                w += "*" + extn
264            choices += w + ")|" + w
265            if not reader.strictExtension:
266                choices += "|any file (*.*)|*.*"
267        # get the file
268        dlg = wx.FileDialog(
269            self, message="Choose "+label+" input file",
270            #defaultDir=os.getcwd(),
271            defaultFile="",
272            wildcard=choices,
273            style=wx.OPEN | wx.CHANGE_DIR
274            )
275        try:
276            if dlg.ShowModal() == wx.ID_OK:
277                file = dlg.GetPath()
278            else: # cancel was pressed
279                return None
280        finally:
281            dlg.Destroy()
282        # set what formats are compatible with this file
283        primaryReaders = []
284        secondaryReaders = []
285        for reader in readerlist:
286            flag = reader.ExtensionValidator(file)
287            if flag is None: 
288                secondaryReaders.append(reader)
289            elif flag:
290                primaryReaders.append(reader)
291        if len(secondaryReaders) + len(primaryReaders) == 0:
292            self.ErrorDialog('No Format','No matching format for file '+file)
293            return None
294       
295        fp = None
296        try:
297            fp = open(file,'r')
298            self.lastimport = file
299            # try the file first with Readers that specify the
300            # files extension and later with ones that allow it
301            for rd in primaryReaders+secondaryReaders:
302                fp.seek(0)  # rewind
303                if not rd.ContentsValidator(fp):
304                    continue # rejected on cursory check
305                try:
306                    fp.seek(0)  # rewind
307                    flag = rd.Reader(file,fp,self)
308                except:
309                    import traceback
310                    print traceback.format_exc()
311                    self.ErrorDialog('Read Error',
312                                     'Error reading file '+file
313                                     +' with format '+ rd.formatName)
314                    continue
315                if not flag: continue
316                return rd
317        except:
318            import traceback
319            print traceback.format_exc()
320            self.ErrorDialog('Open Error','Error on open of file '+file)
321        finally:
322            if fp: fp.close()
323        return None
324
325    def _init_Import_Phase(self,parent):
326        '''import all the G2importphase*.py files that are found in the
327        path and configure the Import Phase menus accordingly
328        '''
329        self.ImportPhaseReaderlist = []
330        self._init_Import_routines(parent,'phase',
331                                   self.ImportPhaseReaderlist,
332                                   'Phase')
333        submenu = wx.Menu()
334        item = parent.AppendMenu(wx.ID_ANY, 'Import Phase menu',
335            submenu, help='Import phase data')
336        item = submenu.Append(wx.ID_ANY,
337                              help='Import phase data based selected by extension',
338                              kind=wx.ITEM_NORMAL,text='Import Phase by extension')
339        self.Bind(wx.EVT_MENU, self.OnImportPhase, id=item.GetId())
340        for reader in self.ImportPhaseReaderlist:
341            item = submenu.Append(wx.ID_ANY,
342                help='Import specific format phase data',
343                kind=wx.ITEM_NORMAL,text='Import Phase '+reader.formatName+'...')
344            self.ImportMenuId[item.GetId()] = reader
345            self.Bind(wx.EVT_MENU, self.OnImportPhase, id=item.GetId())
346
347    def OnImportPhase(self,event):
348        # look up which format was requested
349        reader = self.ImportMenuId.get(event.GetId())
350        rd = self.OnImportGeneric(reader,
351                                  self.ImportPhaseReaderlist,
352                                  'phase')
353        if rd is None: return
354        dlg = wx.TextEntryDialog( # allow editing of phase name
355            self, 'Enter the name for the new phase',
356            'Edit phase name', rd.Phase['General']['Name'],
357            style=wx.OK)
358        dlg.CenterOnParent()
359        if dlg.ShowModal() == wx.ID_OK:
360            rd.Phase['General']['Name'] = dlg.GetValue()
361        dlg.Destroy()
362        PhaseName = rd.Phase['General']['Name']
363        print 'Read phase '+str(PhaseName)+' from file '+str(self.lastimport)
364        self.CheckNotebook()
365        if not G2gd.GetPatternTreeItemId(self,self.root,'Phases'):
366            sub = self.PatternTree.AppendItem(parent=self.root,text='Phases')
367        else:
368            sub = G2gd.GetPatternTreeItemId(self,self.root,'Phases')
369        psub = self.PatternTree.AppendItem(parent=sub,text=PhaseName)
370        self.PatternTree.SetItemPyData(psub,rd.Phase)
371        self.PatternTree.Expand(self.root) # make sure phases are seen
372        self.PatternTree.Expand(sub) 
373        self.PatternTree.Expand(psub) 
374        return # success
375       
376    def _init_Import_Sfact(self,parent):
377        '''import all the G2importsfact*.py files that are found in the
378        path and configure the Import Structure Factor menus accordingly
379        '''
380        self.ImportSfactReaderlist = []
381        self._init_Import_routines(parent,'sfact',
382                                   self.ImportSfactReaderlist,
383                                   'Struct_Factor')
384        submenu = wx.Menu()
385        item = parent.AppendMenu(wx.ID_ANY, 'Import Structure Factor menu',
386            submenu, help='Import Structure Factor data')
387        item = submenu.Append(wx.ID_ANY,
388                              help='Import Structure Factor data based selected by extension',
389                              kind=wx.ITEM_NORMAL,text='Import Structure Factor by extension')
390        self.Bind(wx.EVT_MENU, self.OnImportSfact, id=item.GetId())
391        for reader in self.ImportSfactReaderlist:
392            item = submenu.Append(wx.ID_ANY,
393                help='Import specific format Structure Factor data',
394                kind=wx.ITEM_NORMAL,text='Import Structure Factor '+reader.formatName+'...')
395            self.ImportMenuId[item.GetId()] = reader
396            self.Bind(wx.EVT_MENU, self.OnImportSfact, id=item.GetId())
397
398    def OnImportSfact(self,event):
399        # look up which format was requested
400        reader = self.ImportMenuId.get(event.GetId())
401        rd = self.OnImportGeneric(reader,
402                                  self.ImportSfactReaderlist,
403                                  'Structure Factor')
404        if rd is None: return
405        HistName = ospath.basename(self.lastimport)
406        dlg = wx.TextEntryDialog( # allow editing of Structure Factor name
407            self, 'Enter the name for the new Structure Factor',
408            'Edit Structure Factor name', HistName,
409            style=wx.OK)
410        dlg.CenterOnParent()
411        if dlg.ShowModal() == wx.ID_OK:
412            HistName = dlg.GetValue()
413        dlg.Destroy()
414        print 'Read structure factor table '+str(HistName)+' from file '+str(self.lastimport)
415        self.CheckNotebook()
416        Id = self.PatternTree.AppendItem(parent=self.root,
417                                         text='HKLF '+HistName)
418        self.PatternTree.SetItemPyData(Id,rd.RefList)
419        Sub = self.PatternTree.AppendItem(Id,text='Instrument Parameters')
420        self.PatternTree.SetItemPyData(Sub,rd.Parameters)
421        self.PatternTree.SetItemPyData(
422            self.PatternTree.AppendItem(Id,text='HKL Plot Controls'),
423            rd.Controls)
424        self.PatternTree.SelectItem(Id)
425        self.PatternTree.Expand(Id)
426        self.Sngl = Id
427        return # success
428
429    def _init_coll_Import_Items(self,parent):
430        self.ImportPattern = parent.Append(help='',id=wxID_IMPORTPATTERN, kind=wx.ITEM_NORMAL,
431            text='Import Powder Pattern...')
432        self.ImportHKL = parent.Append(help='',id=wxID_IMPORTHKL, kind=wx.ITEM_NORMAL,
433            text='Import HKLs...')
434        self.Bind(wx.EVT_MENU, self.OnImportPattern, id=wxID_IMPORTPATTERN)
435        self.Bind(wx.EVT_MENU, self.OnImportHKL, id=wxID_IMPORTHKL)
436
437    def _init_coll_Export_Items(self,parent):
438        self.ExportPattern = parent.Append(help='Select PWDR item to enable',id=wxID_EXPORTPATTERN, kind=wx.ITEM_NORMAL,
439            text='Export Powder Patterns...')
440        self.ExportPeakList = parent.Append(help='',id=wxID_EXPORTPEAKLIST, kind=wx.ITEM_NORMAL,
441            text='Export All Peak Lists...')
442        self.ExportHKL = parent.Append(help='',id=wxID_EXPORTHKL, kind=wx.ITEM_NORMAL,
443            text='Export HKLs...')
444        self.ExportPDF = parent.Append(help='Select PDF item to enable',id=wxID_EXPORTPDF, kind=wx.ITEM_NORMAL,
445            text='Export PDF...')
446        self.ExportPhase = parent.Append(help='',id=wxID_EXPORTPHASE, kind=wx.ITEM_NORMAL,
447            text='Export Phase...')
448        self.ExportCIF = parent.Append(help='',id=wxID_EXPORTCIF, kind=wx.ITEM_NORMAL,
449            text='Export CIF...')
450        self.ExportPattern.Enable(False)
451        self.ExportPeakList.Enable(True)
452        self.ExportHKL.Enable(False)
453        self.ExportPDF.Enable(False)
454        self.ExportPhase.Enable(False)
455        self.ExportCIF.Enable(False)
456        self.Bind(wx.EVT_MENU, self.OnExportPatterns, id=wxID_EXPORTPATTERN)
457        self.Bind(wx.EVT_MENU, self.OnExportPeakList, id=wxID_EXPORTPEAKLIST)
458        self.Bind(wx.EVT_MENU, self.OnExportHKL, id=wxID_EXPORTHKL)
459        self.Bind(wx.EVT_MENU, self.OnExportPDF, id=wxID_EXPORTPDF)
460        self.Bind(wx.EVT_MENU, self.OnExportPhase, id=wxID_EXPORTPHASE)
461        self.Bind(wx.EVT_MENU, self.OnExportCIF, id=wxID_EXPORTCIF)
462               
463    def _init_utils(self):
464        self.GSASIIMenu = wx.MenuBar()
465        self.File = wx.Menu(title='')
466        self.Data = wx.Menu(title='')       
467        self.Calculate = wx.Menu(title='')       
468        self.Import = wx.Menu(title='')       
469        self.Export = wx.Menu(title='')       
470
471        self._init_coll_GSASIIMenu_Menus(self.GSASIIMenu)
472        self._init_coll_File_Items(self.File)
473        self._init_coll_Data_Items(self.Data)
474        self._init_coll_Calculate_Items(self.Calculate)
475        self.ImportMenuId = {}
476        self._init_Import_Phase(self.Import)
477        self._init_Import_Sfact(self.Import)
478        self._init_coll_Import_Items(self.Import)
479        self._init_coll_Export_Items(self.Export)
480       
481    def _init_ctrls(self, parent):
482        wx.Frame.__init__(self, name='GSASII', parent=parent,
483            size=wx.Size(300, 250),style=wx.DEFAULT_FRAME_STYLE, title='GSAS-II data tree')
484        clientSize = wx.ClientDisplayRect()
485        Size = self.GetSize()
486        xPos = clientSize[2]-Size[0]
487        self.SetPosition(wx.Point(xPos,clientSize[1]))
488        self._init_utils()
489        self.SetMenuBar(self.GSASIIMenu)
490        self.Bind(wx.EVT_SIZE, self.OnSize)
491        self.CreateStatusBar()
492        self.mainPanel = wx.Panel(self,-1)
493       
494        self.PatternTree = wx.TreeCtrl(id=wxID_PATTERNTREE,
495            parent=self.mainPanel, pos=wx.Point(0, 0),style=wx.TR_DEFAULT_STYLE )
496        self.PatternTree.Bind(wx.EVT_TREE_SEL_CHANGED,
497            self.OnPatternTreeSelChanged, id=wxID_PATTERNTREE)
498        self.PatternTree.Bind(wx.EVT_TREE_ITEM_COLLAPSED,
499            self.OnPatternTreeItemCollapsed, id=wxID_PATTERNTREE)
500        self.PatternTree.Bind(wx.EVT_TREE_ITEM_EXPANDED,
501            self.OnPatternTreeItemExpanded, id=wxID_PATTERNTREE)
502        self.PatternTree.Bind(wx.EVT_TREE_DELETE_ITEM,
503            self.OnPatternTreeItemDelete, id=wxID_PATTERNTREE)
504        self.PatternTree.Bind(wx.EVT_TREE_KEY_DOWN,
505            self.OnPatternTreeKeyDown, id=wxID_PATTERNTREE)
506        self.root = self.PatternTree.AddRoot('Loaded Data: ')
507       
508        plotFrame = wx.Frame(None,-1,'GSASII Plots',size=wx.Size(700,600), \
509            style=wx.DEFAULT_FRAME_STYLE ^ wx.CLOSE_BOX)
510        self.G2plotNB = G2plt.G2PlotNoteBook(plotFrame)
511        plotFrame.Show()
512       
513        self.dataDisplay = None
514       
515    def __init__(self, parent):
516        self._init_ctrls(parent)
517        self.Bind(wx.EVT_CLOSE, self.ExitMain)
518        # various defaults
519        self.oldFocus = None
520        self.GSASprojectfile = ''
521        self.dirname = ospath.expanduser('~')       #start in the users home directory by default; may be meaningless
522        self.undofile = ''
523        self.TreeItemDelete = False
524        self.Offset = [0.0,0.0]
525        self.delOffset = .02
526        self.refOffset = -100.0
527        self.refDelt = .01
528        self.Weight = False
529        self.IparmName = ''
530        self.IfPlot = False
531        self.PatternId = 0
532        self.PickId = 0
533        self.PeakTable = []
534        self.LimitsTable = []
535        self.HKL = []
536        self.Lines = []
537        self.itemPicked = None
538        self.dataFrame = None
539        self.Interpolate = 'nearest'
540        self.ContourColor = 'Paired'
541        self.VcovColor = 'RdYlGn'
542        self.Projection = 'equal area'
543        self.logPlot = False
544        self.qPlot = False
545        self.Contour = False
546        self.Legend = False
547        self.SinglePlot = False
548        self.plotView = 0
549        self.Image = 0
550        self.oldImagefile = ''
551        self.ImageZ = []
552        self.Integrate = 0
553        self.Pwdr = False
554        self.imageDefault = {}
555        self.Sngl = 0
556        self.ifGetRing = False
557        self.setPoly = False
558        arg = sys.argv
559        if len(arg) > 1:
560            self.GSASprojectfile = arg[1]
561            self.dirname = ospath.dirname(arg[1])
562            if self.dirname: os.chdir(self.dirname)
563            G2IO.ProjFileOpen(self)
564            self.PatternTree.Expand(self.root)
565            self.Refine.Enable(True)
566            self.SeqRefine.Enable(True)
567
568    def OnSize(self,event):
569        w,h = self.GetClientSizeTuple()
570        self.mainPanel.SetSize(wx.Size(w,h))
571        self.PatternTree.SetSize(wx.Size(w,h))
572                       
573    def OnPatternTreeSelChanged(self, event):
574        if self.TreeItemDelete:
575            self.TreeItemDelete = False
576        else:
577            pltNum = self.G2plotNB.nb.GetSelection()
578            if pltNum >= 0:                         #to avoid the startup with no plot!
579                pltPage = self.G2plotNB.nb.GetPage(pltNum)
580                pltPlot = pltPage.figure
581            item = event.GetItem()
582            G2gd.MovePatternTreeToGrid(self,item)
583            if self.oldFocus:
584                self.oldFocus.SetFocus()
585       
586    def OnPatternTreeItemCollapsed(self, event):
587        event.Skip()
588
589    def OnPatternTreeItemExpanded(self, event):
590        event.Skip()
591       
592    def OnPatternTreeItemDelete(self, event):
593        self.TreeItemDelete = True
594
595    def OnPatternTreeItemActivated(self, event):
596        event.Skip()
597       
598    def OnPatternTreeKeyDown(self,event):
599        key = event.GetKeyCode()
600        item = self.PickId
601        if type(item) is int: return # is this the toplevel in tree?
602        if key == wx.WXK_UP:
603            self.oldFocus = wx.Window.FindFocus()
604            self.PatternTree.GetPrevSibling(item)
605        elif key == wx.WXK_DOWN:
606            self.oldFocus = wx.Window.FindFocus()
607            self.PatternTree.GetNextSibling(item)
608               
609    def OnPwdrRead(self, event):
610        self.CheckNotebook()
611        dlg = wx.FileDialog(self, 'Choose files', '.', '', 
612            'GSAS fxye files (*.fxye)|*.fxye|GSAS fxy files (*.fxy)|*.fxy|Topas xye files (*.xye)|*.xye|All files (*.*)|*.*', 
613            wx.OPEN | wx.MULTIPLE | wx.CHANGE_DIR)
614        try:
615            if dlg.ShowModal() == wx.ID_OK:
616                filenames = dlg.GetPaths()
617                filenames.sort()
618                for filename in filenames:
619                    Data,Iparm,Comments,Temperature = G2IO.SelectPowderData(self, filename)              #Data: list of tuples (filename,Pos,Bank)
620                    if not Data:                                                    #if Data rejected by user - go to next one
621                        continue
622                    DataType = Iparm['INS   HTYPE ']                                #expect only 4 char string
623                    DataType = DataType.strip()[0:3]                                #just 1st 3 chars
624                    wx.BeginBusyCursor()
625                    Sample = G2pdG.SetDefaultSample()
626                    Sample['Temperature'] = Temperature
627                    try:
628                        for Item in Data:
629                            vals = Item[2].split()          #split up the BANK record
630                            Id = self.PatternTree.AppendItem(parent=self.root,text='PWDR '+ospath.basename(Item[0])+': '+vals[0]+vals[1])
631                            data = G2IO.GetPowderData(filename,Item[1],Item[2],DataType)
632                            self.PatternTree.SetItemPyData(Id,[Item,data])
633                            '''
634                            Each tree item data is a list with:
635                            Item: the (filename,Pos,Bank) tuple
636                            data: (x,y,w,yc,yb,yd) list  of np.arrays from GetPowderData
637                            '''
638                           
639                            self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Comments'),Comments)                           
640                            Tmin = min(data[0])
641                            Tmax = max(data[0])
642                            self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Limits'),[(Tmin,Tmax),[Tmin,Tmax]])
643                            self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Background'),[['chebyschev',True,3,1.0,0.0,0.0],
644                                {'nDebye':0,'debyeTerms':[],'nPeaks':0,'peaksList':[]}])
645       
646                            data = [DataType,]
647                            if 'C' in DataType:
648                                s = Iparm['INS  1 ICONS']
649                                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
650                                if not v[1]:
651                                    names = ['Type','Lam','Zero','Polariz.','U','V','W','X','Y','SH/L','Azimuth'] 
652                                    v = (v[0],v[2],v[4])
653                                    codes = [0,0,0,0]
654                                else:
655                                    names = ['Type','Lam1','Lam2','Zero','I(L2)/I(L1)','Polariz.','U','V','W','X','Y','SH/L','Azimuth']
656                                    codes = [0,0,0,0,0,0]
657                                data.extend(v)
658                                v1 = Iparm['INS  1PRCF1 '].split()                                                 
659                                v = Iparm['INS  1PRCF11'].split()
660                                data.extend([float(v[0]),float(v[1]),float(v[2])])                  #get GU, GV & GW - always here
661                                try:
662                                    azm = float(Iparm['INS  1DETAZM'])
663                                except KeyError:                                                #not in this Iparm file
664                                    azm = 0.0
665                                v = Iparm['INS  1PRCF12'].split()
666                                if v1[0] == 3:
667                                    data.extend([float(v[0]),float(v[1]),float(v[2])+float(v[3],azm)])  #get LX, LY, S+H/L & azimuth
668                                else:
669                                    data.extend([0.0,0.0,0.002,azm])                                      #OK defaults if fxn #3 not 1st in iprm file
670                                codes.extend([0,0,0,0,0,0,0])
671                            self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Instrument Parameters'),[tuple(data),data,codes,names])
672                            self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Sample Parameters'),Sample)
673                            self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Peak List'),[])
674                            self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Index Peak List'),[])
675                            self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Unit Cells List'),[])
676                            self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Reflection Lists'),{})             
677                            self.PatternId = G2gd.GetPatternTreeItemId(self,Id,'Limits')
678                    finally:
679                        wx.EndBusyCursor()
680                self.PatternTree.Expand(Id)
681                self.PatternTree.SelectItem(Id)
682   
683        finally:
684            dlg.Destroy()
685       
686    def OnReadPowderPeaks(self,event):
687        Cuka = 1.54052
688        self.CheckNotebook()
689        dlg = wx.FileDialog(self, 'Choose file with peak list', '.', '', 
690            'peak files (*.txt)|*.txt|All files (*.*)|*.*',wx.OPEN|wx.CHANGE_DIR)
691        try:
692            if dlg.ShowModal() == wx.ID_OK:
693                self.HKL = []
694                self.powderfile = dlg.GetPath()
695                comments,peaks = G2IO.GetPowderPeaks(self.powderfile)
696                Id = self.PatternTree.AppendItem(parent=self.root,text='PKS '+ospath.basename(self.powderfile))
697                data = ['PKS',Cuka,0.0]
698                names = ['Type','Lam','Zero'] 
699                codes = [0,0]
700                self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Instrument Parameters'),[tuple(data),data,codes,names])
701                self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Comments'),comments)
702                self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Index Peak List'),peaks)
703                self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Unit Cells List'),[])             
704                self.PatternTree.Expand(Id)
705                self.PatternTree.SelectItem(Id)
706        finally:
707            dlg.Destroy()
708           
709    def OnImageRead(self,event):
710        self.CheckNotebook()
711        dlg = wx.FileDialog(self, 'Choose image files', '.', '',\
712        'Any image file (*.tif;*.tiff;*.mar*;*.avg;*.sum;*.img;*.G2img)\
713        |*.tif;*.tiff;*.mar*;*.avg;*.sum;*.img;*.G2img|\
714        Any detector tif (*.tif;*.tiff)|*.tif;*.tiff|\
715        MAR file (*.mar*)|*.mar*|\
716        GE Image (*.avg;*.sum)|*.avg;*.sum|\
717        ADSC Image (*.img)|*.img|\
718        GSAS-II Image (*.G2img)|*.G2img|\
719        All files (*.*)|*.*',
720        wx.OPEN | wx.MULTIPLE|wx.CHANGE_DIR)
721        try:
722            if dlg.ShowModal() == wx.ID_OK:
723                imagefiles = dlg.GetPaths()
724                imagefiles.sort()
725                for imagefile in imagefiles:
726                    Comments,Data,Npix,Image = G2IO.GetImageData(self,imagefile)
727                    if Comments:
728                        Id = self.PatternTree.AppendItem(parent=self.root,text='IMG '+ospath.basename(imagefile))
729                        self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Comments'),Comments)
730                        Imax = np.amax(Image)
731                        Imin = max(0.0,np.amin(Image))          #force positive
732                        if self.imageDefault:
733                            Data = copy.copy(self.imageDefault)
734                            Data['showLines'] = True
735                            Data['ring'] = []
736                            Data['rings'] = []
737                            Data['cutoff'] = 10
738                            Data['pixLimit'] = 20
739                            Data['edgemin'] = 100000000
740                            Data['calibdmin'] = 0.5
741                            Data['calibskip'] = 0
742                            Data['ellipses'] = []
743                            Data['calibrant'] = ''
744                        else:
745                            Data['type'] = 'PWDR'
746                            Data['color'] = 'Paired'
747                            Data['tilt'] = 0.0
748                            Data['rotation'] = 0.0
749                            Data['showLines'] = False
750                            Data['ring'] = []
751                            Data['rings'] = []
752                            Data['cutoff'] = 10
753                            Data['pixLimit'] = 20
754                            Data['calibdmin'] = 0.5
755                            Data['calibskip'] = 0
756                            Data['edgemin'] = 100000000
757                            Data['ellipses'] = []
758                            Data['calibrant'] = ''
759                            Data['IOtth'] = [2.0,5.0]
760                            Data['LRazimuth'] = [135,225]
761                            Data['azmthOff'] = 0.0
762                            Data['outChannels'] = 2500
763                            Data['outAzimuths'] = 1
764                            Data['centerAzm'] = False
765                            Data['fullIntegrate'] = False
766                            Data['setRings'] = False
767                            Data['background image'] = ['',1.0]                           
768                        Data['setDefault'] = False
769                        Data['range'] = [(Imin,Imax),[Imin,Imax]]
770                        self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Image Controls'),Data)
771                        Masks = {'Points':[],'Rings':[],'Arcs':[],'Polygons':[],'Thresholds':[(Imin,Imax),[Imin,Imax]]}
772                        self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Masks'),Masks)
773                        self.PatternTree.SetItemPyData(Id,[Npix,imagefile])
774                        self.PickId = Id
775                        self.Image = Id
776                self.PatternTree.SelectItem(G2gd.GetPatternTreeItemId(self,Id,'Image Controls'))             #show last one
777        finally:
778            dlg.Destroy()
779
780    # this will be removed eventually
781    def OnSnglRead(self,event):
782        self.CheckNotebook()
783        dlg = wx.FileDialog(self, 'Choose file', '.', '', 
784            'hkl files (*.hkl)|*.hkl|All files (*.*)|*.*', 
785            wx.OPEN|wx.CHANGE_DIR)
786        try:
787            if dlg.ShowModal() == wx.ID_OK:
788                filename = dlg.GetPath()
789                wx.BeginBusyCursor()
790                try:
791                    Data = {}
792                    names = ['Type','Lam']
793                    HKLref,HKLmin,HKLmax,FoMax,ifFc = G2IO.GetHKLData(filename)
794                    Id = self.PatternTree.AppendItem(parent=self.root,text='HKLF '+ospath.basename(filename))
795                    self.PatternTree.SetItemPyData(Id,HKLref)
796                    Sub = self.PatternTree.AppendItem(Id,text='Instrument Parameters')
797                    data = ['SXC',1.5428,]
798                    self.PatternTree.SetItemPyData(Sub,[tuple(data),data,names])
799                    Data['Type'] = 'Fosq'
800                    Data['ifFc'] = ifFc
801                    Data['HKLmax'] = HKLmax
802                    Data['HKLmin'] = HKLmin
803                    Data['FoMax'] = FoMax
804                    Data['Zone'] = '001'
805                    Data['Layer'] = 0
806                    Data['Scale'] = 1.0
807                    Data['log-lin'] = 'lin'                   
808                    self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='HKL Plot Controls'),Data)
809                    self.PatternTree.SelectItem(Id)
810                    self.PatternTree.Expand(Id)
811                    self.Sngl = Id
812                finally:
813                    wx.EndBusyCursor()   
814        finally:
815            dlg.Destroy()
816           
817    def CheckNotebook(self):
818        '''Make sure the data tree has the minimally expected controls
819        (BHT) correct?
820        '''
821        if not G2gd.GetPatternTreeItemId(self,self.root,'Notebook'):
822            sub = self.PatternTree.AppendItem(parent=self.root,text='Notebook')
823            self.PatternTree.SetItemPyData(sub,[''])
824        if not G2gd.GetPatternTreeItemId(self,self.root,'Controls'):
825            sub = self.PatternTree.AppendItem(parent=self.root,text='Controls')
826            self.PatternTree.SetItemPyData(sub,{})
827        if not G2gd.GetPatternTreeItemId(self,self.root,'Covariance'):
828            sub = self.PatternTree.AppendItem(parent=self.root,text='Covariance')
829            self.PatternTree.SetItemPyData(sub,{})
830        if not G2gd.GetPatternTreeItemId(self,self.root,'Constraints'):
831            sub = self.PatternTree.AppendItem(parent=self.root,text='Constraints')
832            self.PatternTree.SetItemPyData(sub,{'Hist':[],'HAP':[],'Phase':[]})
833        if not G2gd.GetPatternTreeItemId(self,self.root,'Restraints'):
834            sub = self.PatternTree.AppendItem(parent=self.root,text='Restraints')
835            self.PatternTree.SetItemPyData(sub,{})
836           
837               
838    class CopyDialog(wx.Dialog):
839        def __init__(self,parent,title,text,data):
840            wx.Dialog.__init__(self,parent,-1,title, 
841                pos=wx.DefaultPosition,style=wx.DEFAULT_DIALOG_STYLE)
842            self.data = data
843            panel = wx.Panel(self)
844            mainSizer = wx.BoxSizer(wx.VERTICAL)
845            topLabl = wx.StaticText(panel,-1,text)
846            mainSizer.Add((10,10),1)
847            mainSizer.Add(topLabl,0,wx.ALIGN_CENTER_VERTICAL|wx.LEFT,10)
848            mainSizer.Add((10,10),1)
849            ncols = len(data)/40+1
850            dataGridSizer = wx.FlexGridSizer(rows=len(data),cols=ncols,hgap=2,vgap=2)
851            for id,item in enumerate(self.data):
852                ckbox = wx.CheckBox(panel,id,item[1])
853                ckbox.Bind(wx.EVT_CHECKBOX,self.OnCopyChange)                   
854                dataGridSizer.Add(ckbox,0,wx.LEFT,10)
855            mainSizer.Add(dataGridSizer,0,wx.EXPAND)
856            OkBtn = wx.Button(panel,-1,"Ok")
857            OkBtn.Bind(wx.EVT_BUTTON, self.OnOk)
858            cancelBtn = wx.Button(panel,-1,"Cancel")
859            cancelBtn.Bind(wx.EVT_BUTTON, self.OnCancel)
860            btnSizer = wx.BoxSizer(wx.HORIZONTAL)
861            btnSizer.Add((20,20),1)
862            btnSizer.Add(OkBtn)
863            btnSizer.Add((20,20),1)
864            btnSizer.Add(cancelBtn)
865            btnSizer.Add((20,20),1)
866           
867            mainSizer.Add(btnSizer,0,wx.EXPAND|wx.BOTTOM|wx.TOP, 10)
868            panel.SetSizer(mainSizer)
869            panel.Fit()
870            self.Fit()
871       
872        def OnCopyChange(self,event):
873            id = event.GetId()
874            self.data[id][0] = self.FindWindowById(id).GetValue()       
875           
876        def OnOk(self,event):
877            parent = self.GetParent()
878            parent.Raise()
879            self.EndModal(wx.ID_OK)             
880            self.Destroy()
881           
882        def OnCancel(self,event):
883            parent = self.GetParent()
884            parent.Raise()
885            self.EndModal(wx.ID_CANCEL)             
886            self.Destroy()
887           
888        def GetData(self):
889            return self.data
890       
891    class SumDialog(wx.Dialog):
892        def __init__(self,parent,title,text,dataType,data):
893            wx.Dialog.__init__(self,parent,-1,title, 
894                pos=wx.DefaultPosition,style=wx.DEFAULT_DIALOG_STYLE)
895            self.data = data
896            panel = wx.Panel(self)
897            mainSizer = wx.BoxSizer(wx.VERTICAL)
898            topLabl = wx.StaticText(panel,-1,text)
899            mainSizer.Add((10,10),1)
900            mainSizer.Add(topLabl,0,wx.ALIGN_CENTER_VERTICAL|wx.LEFT,10)
901            mainSizer.Add((10,10),1)
902            dataGridSizer = wx.FlexGridSizer(rows=len(data),cols=2,hgap=2,vgap=2)
903            for id,item in enumerate(self.data[:-1]):
904                name = wx.TextCtrl(panel,-1,item[1],size=wx.Size(200,20))
905                name.SetEditable(False)
906                scale = wx.TextCtrl(panel,id,'%.3f'%(item[0]),style=wx.TE_PROCESS_ENTER)
907                scale.Bind(wx.EVT_TEXT_ENTER,self.OnScaleChange)
908                scale.Bind(wx.EVT_KILL_FOCUS,self.OnScaleChange)
909                dataGridSizer.Add(scale,0,wx.LEFT,10)
910                dataGridSizer.Add(name,0,wx.RIGHT,10)
911            if dataType:
912                dataGridSizer.Add(wx.StaticText(panel,-1,'Sum result name: '+dataType),0, \
913                    wx.LEFT|wx.TOP|wx.ALIGN_CENTER_VERTICAL,10)
914                self.name = wx.TextCtrl(panel,-1,self.data[-1],size=wx.Size(200,20),style=wx.TE_PROCESS_ENTER)
915                self.name.Bind(wx.EVT_TEXT_ENTER,self.OnNameChange)
916                self.name.Bind(wx.EVT_KILL_FOCUS,self.OnNameChange)
917                dataGridSizer.Add(self.name,0,wx.RIGHT|wx.TOP,10)
918            mainSizer.Add(dataGridSizer,0,wx.EXPAND)
919            OkBtn = wx.Button(panel,-1,"Ok")
920            OkBtn.Bind(wx.EVT_BUTTON, self.OnOk)
921            cancelBtn = wx.Button(panel,-1,"Cancel")
922            cancelBtn.Bind(wx.EVT_BUTTON, self.OnCancel)
923            btnSizer = wx.BoxSizer(wx.HORIZONTAL)
924            btnSizer.Add((20,20),1)
925            btnSizer.Add(OkBtn)
926            btnSizer.Add((20,20),1)
927            btnSizer.Add(cancelBtn)
928            btnSizer.Add((20,20),1)
929           
930            mainSizer.Add(btnSizer,0,wx.EXPAND|wx.BOTTOM|wx.TOP, 10)
931            panel.SetSizer(mainSizer)
932            panel.Fit()
933            self.Fit()
934
935    class ConstraintDialog(wx.Dialog):
936        '''Window to edit Constraint values
937        '''
938        def __init__(self,parent,title,text,data,separator='*'):
939            wx.Dialog.__init__(self,parent,-1,title, 
940                pos=wx.DefaultPosition,style=wx.DEFAULT_DIALOG_STYLE)
941            self.data = data
942            panel = wx.Panel(self)
943            mainSizer = wx.BoxSizer(wx.VERTICAL)
944            topLabl = wx.StaticText(panel,-1,text)
945            mainSizer.Add((10,10),1)
946            mainSizer.Add(topLabl,0,wx.ALIGN_CENTER_VERTICAL|wx.LEFT,10)
947            mainSizer.Add((10,10),1)
948            dataGridSizer = wx.FlexGridSizer(rows=len(data),cols=2,hgap=2,vgap=2)
949            for id,item in enumerate(self.data[:-1]):
950                lbl = item[1]
951                if lbl[-1] != '=': lbl += ' ' + separator + ' '
952                name = wx.StaticText(panel,-1,lbl,size=wx.Size(200,20),
953                                     style=wx.ALIGN_RIGHT)
954                scale = wx.TextCtrl(panel,id,'%.3f'%(item[0]),style=wx.TE_PROCESS_ENTER)
955                scale.Bind(wx.EVT_TEXT_ENTER,self.OnScaleChange)
956                scale.Bind(wx.EVT_KILL_FOCUS,self.OnScaleChange)
957                dataGridSizer.Add(name,0,wx.LEFT,10)
958                dataGridSizer.Add(scale,0,wx.RIGHT,10)
959            mainSizer.Add(dataGridSizer,0,wx.EXPAND)
960            OkBtn = wx.Button(panel,-1,"Ok")
961            OkBtn.Bind(wx.EVT_BUTTON, self.OnOk)
962            cancelBtn = wx.Button(panel,-1,"Cancel")
963            cancelBtn.Bind(wx.EVT_BUTTON, self.OnCancel)
964            btnSizer = wx.BoxSizer(wx.HORIZONTAL)
965            btnSizer.Add((20,20),1)
966            btnSizer.Add(OkBtn)
967            btnSizer.Add((20,20),1)
968            btnSizer.Add(cancelBtn)
969            btnSizer.Add((20,20),1)
970           
971            mainSizer.Add(btnSizer,0,wx.EXPAND|wx.BOTTOM|wx.TOP, 10)
972            panel.SetSizer(mainSizer)
973            panel.Fit()
974            self.Fit()
975            self.CenterOnParent()
976           
977        def OnNameChange(self,event):
978            self.data[-1] = self.name.GetValue() 
979           
980        def OnScaleChange(self,event):
981            id = event.GetId()
982            value = self.FindWindowById(id).GetValue()
983            try:
984                self.data[id][0] = float(value)
985                self.FindWindowById(id).SetValue('%.3f'%(self.data[id][0]))
986            except ValueError:
987                if value and '-' not in value[0]:
988                    print 'bad input - numbers only'
989                    self.FindWindowById(id).SetValue('0.000')
990           
991        def OnOk(self,event):
992            parent = self.GetParent()
993            parent.Raise()
994            self.EndModal(wx.ID_OK)             
995            #self.Destroy() -- do this later, after using GetData
996           
997        def OnCancel(self,event):
998            parent = self.GetParent()
999            parent.Raise()
1000            self.EndModal(wx.ID_CANCEL)             
1001            #self.Destroy()
1002           
1003        def GetData(self):
1004            return self.data
1005           
1006    def OnPwdrSum(self,event):
1007        TextList = []
1008        DataList = []
1009        SumList = []
1010        Names = []
1011        Inst = []
1012        SumItemList = []
1013        Comments = ['Sum equals: \n']
1014        if self.PatternTree.GetCount():
1015            item, cookie = self.PatternTree.GetFirstChild(self.root)
1016            while item:
1017                name = self.PatternTree.GetItemText(item)
1018                Names.append(name)
1019                if 'PWDR' in name:
1020                    TextList.append([0.0,name])
1021                    DataList.append(self.PatternTree.GetItemPyData(item)[1])    # (x,y,w,yc,yb,yd)
1022                    if not Inst:
1023                        Inst = self.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(self,item, 'Instrument Parameters'))
1024                item, cookie = self.PatternTree.GetNextChild(self.root, cookie)
1025            if len(TextList) < 2:
1026                self.ErrorDialog('Not enough data to sum','There must be more than one "PWDR" pattern')
1027                return
1028            TextList.append('default_sum_name')               
1029            dlg = self.SumDialog(self,'Sum data','Enter scale for each pattern in summation','PWDR',TextList)
1030            try:
1031                if dlg.ShowModal() == wx.ID_OK:
1032                    lenX = 0
1033                    Xminmax = [0,0]
1034                    Xsum = []
1035                    Ysum = []
1036                    Vsum = []
1037                    result = dlg.GetData()
1038                    for i,item in enumerate(result[:-1]):
1039                        scale,name = item
1040                        data = DataList[i]
1041                        if scale:
1042                            Comments.append("%10.3f %s" % (scale,' * '+name))
1043                            x,y,w,yc,yb,yd = data   #numpy arrays!
1044                            v = 1./w
1045                            if lenX:
1046                                if lenX != len(x):
1047                                    self.ErrorDialog('Data length error','Data to be summed must have same number of points'+ \
1048                                        '\nExpected:'+str(lenX)+ \
1049                                        '\nFound:   '+str(len(x))+'\nfor '+name)
1050                                    return
1051                            else:
1052                                lenX = len(x)
1053                            if Xminmax[1]:
1054                                if Xminmax != [x[0],x[-1]]:
1055                                    self.ErrorDialog('Data range error','Data to be summed must span same range'+ \
1056                                        '\nExpected:'+str(Xminmax[0])+' '+str(Xminmax[1])+ \
1057                                        '\nFound:   '+str(x[0])+' '+str(x[-1])+'\nfor '+name)
1058                                    return
1059                                else:
1060                                    for j,yi in enumerate(y):
1061                                         Ysum[j] += scale*yi
1062                                         Vsum[j] += abs(scale)*v[j]
1063                            else:
1064                                Xminmax = [x[0],x[-1]]
1065                                YCsum = YBsum = YDsum = [0.0 for i in range(lenX)]
1066                                for j,yi in enumerate(y):
1067                                    Xsum.append(x[j])
1068                                    Ysum.append(scale*yi)
1069                                    Vsum.append(abs(scale*v[j]))
1070                    Wsum = 1./np.array(Vsum)
1071                    outname = 'PWDR '+result[-1]
1072                    Id = 0
1073                    if outname in Names:
1074                        dlg2 = wx.MessageDialog(self,'Overwrite data?','Duplicate data name',wx.OK|wx.CANCEL)
1075                        try:
1076                            if dlg2.ShowModal() == wx.ID_OK:
1077                                Id = G2gd.GetPatternTreeItemId(self,self.root,name)
1078                                self.PatternTree.Delete(Id)
1079                        finally:
1080                            dlg2.Destroy()
1081                    Id = self.PatternTree.AppendItem(parent=self.root,text=outname)
1082                    if Id:
1083                        Sample = G2pdG.SetDefaultSample()
1084                        self.PatternTree.SetItemPyData(Id,[[''],[np.array(Xsum),np.array(Ysum),np.array(Wsum),
1085                            np.array(YCsum),np.array(YBsum),np.array(YDsum)]])
1086                        self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Comments'),Comments)                   
1087                        self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Limits'),[tuple(Xminmax),Xminmax])
1088                        self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Background'),[['chebyschev',True,3,1.0,0.0,0.0],
1089                            {'nDebye':0,'debyeTerms':[],'nPeaks':0,'peaksList':[]}])
1090                        self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Instrument Parameters'),Inst)
1091                        self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Sample Parameters'),Sample)
1092                        self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Peak List'),[])
1093                        self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Index Peak List'),[])
1094                        self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Unit Cells List'),[])             
1095                        self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Reflection Lists'),{})             
1096                        self.PatternTree.SelectItem(Id)
1097                        self.PatternTree.Expand(Id)
1098                   
1099            finally:
1100                dlg.Destroy()
1101
1102    def OnImageSum(self,event):
1103        TextList = []
1104        DataList = []
1105        SumList = []
1106        Names = []
1107        Inst = []
1108        SumItemList = []
1109        Comments = ['Sum equals: \n']
1110        if self.PatternTree.GetCount():
1111            item, cookie = self.PatternTree.GetFirstChild(self.root)
1112            while item:
1113                name = self.PatternTree.GetItemText(item)
1114                Names.append(name)
1115                if 'IMG' in name:
1116                    TextList.append([0.0,name])
1117                    DataList.append(self.PatternTree.GetItemPyData(item))        #Size,Image
1118                    Data = self.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(self,item,'Image Controls'))
1119                item, cookie = self.PatternTree.GetNextChild(self.root, cookie)
1120            if len(TextList) < 2:
1121                self.ErrorDialog('Not enough data to sum','There must be more than one "IMG" pattern')
1122                return
1123            TextList.append('default_sum_name')               
1124            dlg = self.SumDialog(self,'Sum data','Enter scale for each image in summation','IMG',TextList)
1125            try:
1126                if dlg.ShowModal() == wx.ID_OK:
1127                    imSize = 0
1128                    result = dlg.GetData()
1129                    First = True
1130                    Found = False
1131                    for i,item in enumerate(result[:-1]):
1132                        scale,name = item
1133                        data = DataList[i]
1134                        if scale:
1135                            Found = True                               
1136                            Comments.append("%10.3f %s" % (scale,' * '+name))
1137                            Npix,imagefile = data
1138                            image = G2IO.GetImageData(self,imagefile,imageOnly=True)
1139                            if First:
1140                                newImage = np.zeros_like(image)
1141                                First = False
1142                            if imSize:
1143                                if imSize != Npix:
1144                                    self.ErrorDialog('Image size error','Images to be summed must be same size'+ \
1145                                        '\nExpected:'+str(imSize)+ \
1146                                        '\nFound:   '+str(Npix)+'\nfor '+name)
1147                                    return
1148                                newImage = newImage+scale*image
1149                            else:
1150                                imSize = Npix
1151                                newImage = newImage+scale*image
1152                            del(image)
1153                    if not Found:
1154                        self.ErrorDialog('Image sum error','No nonzero image multipliers found')
1155                        return
1156                       
1157                    newImage = np.asfarray(newImage,dtype=np.float32)                       
1158                    outname = 'IMG '+result[-1]
1159                    Id = 0
1160                    if outname in Names:
1161                        dlg2 = wx.MessageDialog(self,'Overwrite data?','Duplicate data name',wx.OK|wx.CANCEL)
1162                        try:
1163                            if dlg2.ShowModal() == wx.ID_OK:
1164                                Id = G2gd.GetPatternTreeItemId(self,self.root,name)
1165                        finally:
1166                            dlg2.Destroy()
1167                    else:
1168                        Id = self.PatternTree.AppendItem(parent=self.root,text=outname)
1169                    if Id:
1170                        dlg = wx.FileDialog(self, 'Choose sum image filename', '.', '', 
1171                            'G2img files (*.G2img)|*.G2img', 
1172                            wx.SAVE|wx.FD_OVERWRITE_PROMPT|wx.CHANGE_DIR)
1173                        if dlg.ShowModal() == wx.ID_OK:
1174                            newimagefile = dlg.GetPath()
1175                            newimagefile = G2IO.FileDlgFixExt(dlg,newimagefile)
1176                            G2IO.PutG2Image(newimagefile,Comments,Data,Npix,newImage)
1177                            Imax = np.amax(newImage)
1178                            Imin = np.amin(newImage)
1179                            newImage = []
1180                            self.PatternTree.SetItemPyData(Id,[imSize,newimagefile])
1181                            self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Comments'),Comments)
1182                        del(newImage)
1183                        if self.imageDefault:
1184                            Data = copy.copy(self.imageDefault)
1185                        Data['showLines'] = True
1186                        Data['ring'] = []
1187                        Data['rings'] = []
1188                        Data['cutoff'] = 10
1189                        Data['pixLimit'] = 20
1190                        Data['ellipses'] = []
1191                        Data['calibrant'] = ''
1192                        Data['range'] = [(Imin,Imax),[Imin,Imax]]
1193                        self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Image Controls'),Data)                                           
1194                        Masks = {'Points':[],'Rings':[],'Arcs':[],'Polygons':[],'Thresholds':[(Imin,Imax),[Imin,Imax]]}
1195                        self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Masks'),Masks)
1196                        self.PatternTree.SelectItem(Id)
1197                        self.PatternTree.Expand(Id)
1198                        self.PickId = G2gd.GetPatternTreeItemId(self,self.root,outname)
1199                        self.Image = self.PickId
1200            finally:
1201                dlg.Destroy()
1202                     
1203    def OnAddPhase(self,event):
1204        if not G2gd.GetPatternTreeItemId(self,self.root,'Phases'):
1205            sub = self.PatternTree.AppendItem(parent=self.root,text='Phases')
1206        else:
1207            sub = G2gd.GetPatternTreeItemId(self,self.root,'Phases')
1208        PhaseName = ''
1209        dlg = wx.TextEntryDialog(None,'Enter a name for this phase','Phase Name Entry','New phase',
1210            style=wx.OK)
1211        if dlg.ShowModal() == wx.ID_OK:
1212            PhaseName = dlg.GetValue()
1213        dlg.Destroy()
1214        sub = self.PatternTree.AppendItem(parent=sub,text=PhaseName)
1215        E,SGData = G2spc.SpcGroup('P 1')
1216        self.PatternTree.SetItemPyData(sub,G2IO.SetNewPhase(Name=PhaseName,SGData=SGData))
1217       
1218    def OnDeletePhase(self,event):
1219        #Hmm, also need to delete this phase from Reflection Lists for each PWDR histogram
1220        if self.dataFrame:
1221            self.dataFrame.Clear() 
1222        TextList = []
1223        DelList = []
1224        DelItemList = []
1225        if G2gd.GetPatternTreeItemId(self,self.root,'Phases'):
1226            sub = G2gd.GetPatternTreeItemId(self,self.root,'Phases')
1227        else:
1228            return
1229        if sub:
1230            item, cookie = self.PatternTree.GetFirstChild(sub)
1231            while item:
1232                TextList.append(self.PatternTree.GetItemText(item))
1233                item, cookie = self.PatternTree.GetNextChild(sub, cookie)               
1234            dlg = wx.MultiChoiceDialog(self, 'Which phase to delete?', 'Delete phase', TextList, wx.CHOICEDLG_STYLE)
1235            try:
1236                if dlg.ShowModal() == wx.ID_OK:
1237                    result = dlg.GetSelections()
1238                    for i in result: DelList.append([i,TextList[i]])
1239                    item, cookie = self.PatternTree.GetFirstChild(sub)
1240                    i = 0
1241                    while item:
1242                        if [i,self.PatternTree.GetItemText(item)] in DelList: DelItemList.append(item)
1243                        item, cookie = self.PatternTree.GetNextChild(sub, cookie)
1244                        i += 1
1245                    for item in DelItemList:
1246                        name = self.PatternTree.GetItemText(item)
1247                        self.PatternTree.Delete(item)
1248                        self.G2plotNB.Delete(name)
1249                    item, cookie = self.PatternTree.GetFirstChild(self.root)
1250                    while item:
1251                        name = self.PatternTree.GetItemText(item)
1252                        if 'PWDR' in name:
1253                            Id = G2gd.GetPatternTreeItemId(self,item, 'Reflection Lists')
1254                            refList = self.PatternTree.GetItemPyData(Id)
1255                            for i,item in DelList:
1256                                del(refList[item])
1257                            self.PatternTree.SetItemPyData(Id,refList)
1258                        item, cookie = self.PatternTree.GetNextChild(self.root, cookie)
1259            finally:
1260                dlg.Destroy()
1261               
1262    def OnRenameData(self,event):
1263        name = self.PatternTree.GetItemText(self.PickId)     
1264        if 'PWDR' in name or 'HKLF' in name or 'IMG' in name:
1265            dataType = name[:name.index(' ')+1]                 #includes the ' '
1266            dlg = wx.TextEntryDialog(self,'Data name: '+dataType,'Change data name',
1267                defaultValue=name[name.index(' ')+1:])
1268            try:
1269                if dlg.ShowModal() == wx.ID_OK:
1270                    self.PatternTree.SetItemText(self.PickId,dataType+dlg.GetValue())
1271            finally:
1272                dlg.Destroy()
1273       
1274    def GetFileList(self,fileType,skip=None):        #potentially useful?
1275        fileList = []
1276        Source = ''
1277        id, cookie = self.PatternTree.GetFirstChild(self.root)
1278        while id:
1279            name = self.PatternTree.GetItemText(id)
1280            if fileType in name:
1281                if id == skip:
1282                    Source = name
1283                else:
1284                    fileList.append([False,name,id])
1285            id, cookie = self.PatternTree.GetNextChild(self.root, cookie)
1286        if skip:
1287            return fileList,Source
1288        else:
1289            return fileList
1290           
1291    def OnDataDelete(self, event):
1292        TextList = ['All Data']
1293        DelList = []
1294        DelItemList = []
1295        ifPWDR = False
1296        ifIMG = False
1297        ifHKLF = False
1298        ifPDF = False
1299        if self.PatternTree.GetCount():
1300            item, cookie = self.PatternTree.GetFirstChild(self.root)
1301            while item:
1302                name = self.PatternTree.GetItemText(item)
1303                if name not in ['Notebook','Controls','Covariance','Constraints','Restraints','Phases']:
1304                    if 'PWDR' in name: ifPWDR = True
1305                    if 'IMG' in name: ifIMG = True
1306                    if 'HKLF' in name: ifHKLF = True
1307                    if 'PDF' in name: ifPDF = True
1308                    TextList.append(name)
1309                item, cookie = self.PatternTree.GetNextChild(self.root, cookie)
1310            if ifPWDR: TextList.insert(1,'All PWDR')
1311            if ifIMG: TextList.insert(1,'All IMG')
1312            if ifHKLF: TextList.insert(1,'All HKLF')
1313            if ifPDF: TextList.insert(1,'All PDF')               
1314            dlg = wx.MultiChoiceDialog(self, 'Which data to delete?', 'Delete data', TextList, wx.CHOICEDLG_STYLE)
1315            try:
1316                if dlg.ShowModal() == wx.ID_OK:
1317                    result = dlg.GetSelections()
1318                    for i in result: DelList.append(TextList[i])
1319                    if 'All Data' in DelList:
1320                        DelList = [item for item in TextList if item[:3] != 'All']
1321                    elif 'All PWDR' in DelList:
1322                        DelList = [item for item in TextList if item[:4] == 'PWDR']
1323                    elif 'All IMG' in DelList:
1324                        DelList = [item for item in TextList if item[:3] == 'IMG']
1325                    elif 'All HKLF' in DelList:
1326                        DelList = [item for item in TextList if item[:4] == 'HKLF']
1327                    elif 'All PDF' in DelList:
1328                        DelList = [item for item in TextList if item[:3] == 'PDF']
1329                    item, cookie = self.PatternTree.GetFirstChild(self.root)
1330                    while item:
1331                        if self.PatternTree.GetItemText(item) in DelList: DelItemList.append(item)
1332                        item, cookie = self.PatternTree.GetNextChild(self.root, cookie)
1333                    for item in DelItemList:
1334                        self.PatternTree.Delete(item)
1335                    G2plt.PlotPatterns(self,True)                        #so plot gets updated
1336            finally:
1337                dlg.Destroy()
1338
1339    def OnFileOpen(self, event):
1340        result = ''
1341        Id = 0
1342        if self.PatternTree.GetChildrenCount(self.root,False):
1343            if self.dataFrame:
1344                self.dataFrame.Clear() 
1345            dlg = wx.MessageDialog(self, 'Overwrite?','Project exists!',  wx.OK | wx.CANCEL)
1346            try:
1347                result = dlg.ShowModal()
1348                if result == wx.ID_OK:
1349                    self.PatternTree.DeleteChildren(self.root)
1350                    self.GSASprojectfile = ''
1351#                    self.PatternTree.DeleteChildren(self.root)
1352                    if self.HKL: self.HKL = []
1353                    if self.G2plotNB.plotList:
1354                        self.G2plotNB.clear()
1355            finally:
1356                dlg.Destroy()
1357        if result != wx.ID_CANCEL:   
1358            if self.dataDisplay: self.dataDisplay.Destroy()
1359            dlg = wx.FileDialog(self, 'Choose GSAS-II project file', '.', '', 
1360                'GSAS-II project file (*.gpx)|*.gpx',wx.OPEN|wx.CHANGE_DIR)
1361            try:
1362                if dlg.ShowModal() == wx.ID_OK:
1363                    self.GSASprojectfile = dlg.GetPath()
1364                    self.GSASprojectfile = G2IO.FileDlgFixExt(dlg,self.GSASprojectfile)
1365                    self.dirname = dlg.GetDirectory()
1366                    G2IO.ProjFileOpen(self)
1367                    self.PatternTree.SetItemText(self.root,'Loaded Data: '+self.GSASprojectfile)
1368                    self.PatternTree.Expand(self.root)
1369                    self.HKL = []
1370                    item, cookie = self.PatternTree.GetFirstChild(self.root)
1371                    while item and not Id:
1372                        name = self.PatternTree.GetItemText(item)
1373                        if name[:4] in ['PWDR','HKLF','IMG ','PDF ']:
1374                            Id = item
1375                        elif name == 'Controls':
1376                            data = self.PatternTree.GetItemPyData(item)
1377                            if data:
1378                                self.Refine.Enable(True)
1379                                self.SeqRefine.Enable(True)
1380                        item, cookie = self.PatternTree.GetNextChild(self.root, cookie)               
1381                    if Id:
1382                        self.PatternTree.SelectItem(Id)
1383                    self.CheckNotebook()
1384            finally:
1385                dlg.Destroy()
1386
1387
1388    def OnFileClose(self, event):
1389        if self.dataFrame:
1390            self.dataFrame.Clear()
1391            self.dataFrame.SetLabel('GSAS-II data display') 
1392        dlg = wx.MessageDialog(self, 'Save current project?', ' ', wx.YES | wx.NO | wx.CANCEL)
1393        try:
1394            result = dlg.ShowModal()
1395            if result == wx.ID_OK:
1396                self.OnFileSaveMenu(event)
1397            if result != wx.ID_CANCEL:
1398                self.GSASprojectfile = ''
1399                self.PatternTree.SetItemText(self.root,'Loaded Data: ')
1400                self.PatternTree.DeleteChildren(self.root)
1401                if self.HKL: self.HKL = []
1402                if self.G2plotNB.plotList:
1403                    self.G2plotNB.clear()
1404        finally:
1405            dlg.Destroy()
1406
1407    def OnFileSave(self, event):
1408        if self.GSASprojectfile: 
1409            self.PatternTree.SetItemText(self.root,'Loaded Data: '+self.GSASprojectfile)
1410            G2IO.ProjFileSave(self)
1411        else:
1412            self.OnFileSaveas(event)
1413
1414    def OnFileSaveas(self, event):
1415        dlg = wx.FileDialog(self, 'Choose GSAS-II project file name', '.', '', 
1416            'GSAS-II project file (*.gpx)|*.gpx',wx.FD_SAVE|wx.FD_OVERWRITE_PROMPT|wx.CHANGE_DIR)
1417        try:
1418            if dlg.ShowModal() == wx.ID_OK:
1419                self.GSASprojectfile = dlg.GetPath()
1420                self.GSASprojectfile = G2IO.FileDlgFixExt(dlg,self.GSASprojectfile)
1421                self.PatternTree.SetItemText(self.root,'Loaded Data: '+self.GSASprojectfile)
1422                G2IO.ProjFileSave(self)
1423                self.dirname = dlg.GetDirectory()
1424        finally:
1425            dlg.Destroy()
1426
1427    def ExitMain(self, event):
1428        if self.undofile:
1429            os.remove(self.undofile)
1430        sys.exit()
1431       
1432    def OnFileExit(self, event):
1433        if self.dataFrame:
1434            self.dataFrame.Clear() 
1435            self.dataFrame.Destroy()
1436        self.Close()
1437       
1438    def OnImportPattern(self,event):
1439        dlg = wx.FileDialog(self, 'Choose nonGSAS powder file', '.', '', 
1440            '(*.*)|*.*',wx.OPEN|wx.CHANGE_DIR)
1441        try:
1442            if dlg.ShowModal() == wx.ID_OK:
1443                self.powderfile = dlg.GetPath()
1444        finally:
1445            dlg.Destroy()
1446           
1447    def OnImportHKL(self,event):
1448        dlg = wx.FileDialog(self, 'Choose structure factor file', '.', '', 
1449            '(*.*)|*.*',wx.OPEN|wx.CHANGE_DIR)
1450        try:
1451            if dlg.ShowModal() == wx.ID_OK:
1452                self.HKLfile = dlg.GetPath()
1453        finally:
1454            dlg.Destroy()
1455       
1456    def OnExportPatterns(self,event):
1457        names = ['All']
1458        exports = []
1459        item, cookie = self.PatternTree.GetFirstChild(self.root)
1460        while item:
1461            name = self.PatternTree.GetItemText(item)
1462            if 'PWDR' in name:
1463                names.append(name)
1464            item, cookie = self.PatternTree.GetNextChild(self.root, cookie)
1465        if names:
1466            dlg = wx.MultiChoiceDialog(self,'Select','Powder patterns to export',names)
1467            if dlg.ShowModal() == wx.ID_OK:
1468                sel = dlg.GetSelections()
1469                if sel[0] == 0:
1470                    exports = names[1:]
1471                else:
1472                    for x in sel:
1473                        exports.append(names[x])
1474            dlg.Destroy()
1475        if exports:
1476            dlg = wx.FileDialog(self, 'Choose output powder file name', '.', '', 
1477                'GSAS fxye file (*.fxye)|*.fxye|xye file (*.xye)|*.xye',
1478                wx.FD_SAVE|wx.FD_OVERWRITE_PROMPT|wx.CHANGE_DIR)
1479            try:
1480                if dlg.ShowModal() == wx.ID_OK:
1481                    powderfile = dlg.GetPath()
1482                    powderfile = G2IO.FileDlgFixExt(dlg,powderfile)
1483                    if 'fxye' in powderfile:
1484                        G2IO.powderFxyeSave(self,exports,powderfile)
1485                    else:       #just xye
1486                        G2IO.powderXyeSave(self,exports,powderfile)
1487            finally:
1488                dlg.Destroy()
1489       
1490    def OnExportPeakList(self,event):
1491        dlg = wx.FileDialog(self, 'Choose output peak list file name', '.', '', 
1492            '(*.*)|*.*',wx.FD_SAVE|wx.FD_OVERWRITE_PROMPT|wx.CHANGE_DIR)
1493        try:
1494            if dlg.ShowModal() == wx.ID_OK:
1495                self.peaklistfile = dlg.GetPath()
1496                self.peaklistfile = G2IO.FileDlgFixExt(dlg,self.peaklistfile)
1497                file = open(self.peaklistfile,'w')               
1498                item, cookie = self.PatternTree.GetFirstChild(self.root)
1499                while item:
1500                    name = self.PatternTree.GetItemText(item)
1501                    if 'PWDR' in name:
1502                        item2, cookie2 = self.PatternTree.GetFirstChild(item)
1503                        while item2:
1504                            name2 = self.PatternTree.GetItemText(item2)
1505                            if name2 == 'Peak List':
1506                                peaks = self.PatternTree.GetItemPyData(item2)
1507                                file.write("%s \n" % (name+' Peak List'))               
1508                                for peak in peaks:
1509                                    file.write("%10.4f %12.2f %10.3f %10.3f \n" % \
1510                                        (peak[0],peak[2],peak[4],peak[6]))
1511                            item2, cookie2 = self.PatternTree.GetNextChild(item, cookie2)                           
1512                    item, cookie = self.PatternTree.GetNextChild(self.root, cookie)                           
1513                file.close()
1514        finally:
1515            dlg.Destroy()
1516       
1517    def OnExportHKL(self,event):
1518        event.Skip()
1519       
1520    def OnExportPDF(self,event):
1521        #need S(Q) and G(R) to be saved here - probably best from selection?
1522        names = ['All']
1523        exports = []
1524        item, cookie = self.PatternTree.GetFirstChild(self.root)
1525        while item:
1526            name = self.PatternTree.GetItemText(item)
1527            if 'PDF' in name:
1528                names.append(name)
1529            item, cookie = self.PatternTree.GetNextChild(self.root, cookie)
1530        if names:
1531            dlg = wx.MultiChoiceDialog(self,'Select','PDF patterns to export',names)
1532            if dlg.ShowModal() == wx.ID_OK:
1533                sel = dlg.GetSelections()
1534                if sel[0] == 0:
1535                    exports = names[1:]
1536                else:
1537                    for x in sel:
1538                        exports.append(names[x])
1539            dlg.Destroy()
1540        if exports:
1541            G2IO.PDFSave(self,exports)
1542       
1543    def OnExportPhase(self,event):
1544        event.Skip()
1545       
1546    def OnExportCIF(self,event):
1547        event.Skip()
1548
1549    def OnMakePDFs(self,event):
1550        tth2q = lambda t,w:4.0*math.pi*sind(t/2.0)/w
1551        TextList = ['All PWDR']
1552        PDFlist = []
1553        Names = []
1554        if self.PatternTree.GetCount():
1555            id, cookie = self.PatternTree.GetFirstChild(self.root)
1556            while id:
1557                name = self.PatternTree.GetItemText(id)
1558                Names.append(name)
1559                if 'PWDR' in name:
1560                    TextList.append(name)
1561                id, cookie = self.PatternTree.GetNextChild(self.root, cookie)
1562            if len(TextList) == 1:
1563                self.ErrorDialog('Nothing to make PDFs for','There must be at least one "PWDR" pattern')
1564                return
1565            dlg = wx.MultiChoiceDialog(self,'Make PDF controls','Make PDF controls for:',TextList, wx.CHOICEDLG_STYLE)
1566            try:
1567                if dlg.ShowModal() == wx.ID_OK:
1568                    result = dlg.GetSelections()
1569                    for i in result: PDFlist.append(TextList[i])
1570                    if 0 in result:
1571                        PDFlist = [item for item in TextList if item[:4] == 'PWDR']                       
1572                    for item in PDFlist:
1573                        PWDRname = item[4:]
1574                        Id = self.PatternTree.AppendItem(parent=self.root,text='PDF '+PWDRname)
1575                        Data = {
1576                            'Sample':{'Name':item,'Mult':1.0,'Add':0.0},
1577                            'Sample Bkg.':{'Name':'','Mult':-1.0,'Add':0.0},
1578                            'Container':{'Name':'','Mult':-1.0,'Add':0.0},
1579                            'Container Bkg.':{'Name':'','Mult':-1.0,'Add':0.0},'ElList':{},
1580                            'Geometry':'Cylinder','Diam':1.0,'Pack':0.50,'Form Vol':10.0,
1581                            'DetType':'Image plate','ObliqCoeff':0.2,'Ruland':0.025,'QScaleLim':[0,100],
1582                            'Lorch':True,}
1583                        self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='PDF Controls'),Data)
1584                        self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='I(Q)'+PWDRname),[])       
1585                        self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='S(Q)'+PWDRname),[])       
1586                        self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='F(Q)'+PWDRname),[])       
1587                        self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='G(R)'+PWDRname),[])       
1588                self.ExportPDF.Enable(True)
1589            finally:
1590                dlg.Destroy()
1591               
1592    def GetPWDRdatafromTree(self,PWDRname):
1593        ''' Returns powder data from GSASII tree
1594        input:
1595            PWDRname = powder histogram name as obtained from GetHistogramNames
1596        return:
1597            PWDRdata = powder data dictionary with:
1598                Data - powder data arrays, Limits, Instrument Parameters, Sample Parameters           
1599        '''
1600        PWDRdata = {}
1601        PWDRdata['Data'] = self.PatternTree.GetItemPyData(PWDRname)[1]          #powder data arrays
1602        PWDRdata['Limits'] = self.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(self,PWDRname,'Limits'))
1603        PWDRdata['Background'] = self.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(self,PWDRname,'Background'))
1604        PWDRdata['Instrument Parameters'] = self.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(self,PWDRname,'Instrument Parameters'))
1605        PWDRdata['Sample Parameters'] = self.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(self,PWDRname,'Sample Parameters'))
1606        PWDRdata['Reflection Lists'] = self.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(self,PWDRname,'Reflection Lists'))
1607        return PWDRdata
1608
1609    def GetHKLFdatafromTree(self,HKLFname):
1610        ''' Returns single crystal data from GSASII tree
1611        input:
1612            HKLFname = single crystal histogram name as obtained from GetHistogramNames
1613        return:
1614            HKLFdata = single crystal data list of reflections: for each reflection:
1615                HKLF = [np.array([h,k,l]),FoSq,sigFoSq,FcSq,Fcp,Fcpp,phase]
1616        '''
1617        HKLFdata = []
1618        while True:
1619            data = self.PatternTree.GetItemPyData(HKLFname)
1620            datum = data[0]
1621            if datum[0] == HKLFname:
1622                HKLFdata = datum[1:][0]
1623        return HKLFdata
1624                   
1625    def GetUsedHistogramsAndPhasesfromTree(self):
1626        ''' Returns all histograms that are found in any phase
1627        and any phase that uses a histogram
1628        return:
1629            Histograms = dictionary of histograms as {name:data,...}
1630            Phases = dictionary of phases that use histograms
1631        '''
1632        phaseData = {}
1633        if G2gd.GetPatternTreeItemId(self,self.root,'Phases'):
1634            sub = G2gd.GetPatternTreeItemId(self,self.root,'Phases')
1635        else:
1636            print 'no phases to be refined'
1637            return
1638        if sub:
1639            item, cookie = self.PatternTree.GetFirstChild(sub)
1640            while item:
1641                phaseData[self.PatternTree.GetItemText(item)] =  self.PatternTree.GetItemPyData(item)               
1642                item, cookie = self.PatternTree.GetNextChild(sub, cookie)               
1643        Histograms = {}
1644        Phases = {}
1645        pId = 0
1646        hId = 0
1647        for phase in phaseData:
1648            Phase = phaseData[phase]
1649            if Phase['Histograms']:
1650                if phase not in Phases:
1651                    Phase['pId'] = pId
1652                    pId += 1
1653                    Phases[phase] = Phase
1654                for hist in Phase['Histograms']:
1655                    if hist not in Histograms:
1656                        item = G2gd.GetPatternTreeItemId(self,self.root,hist)
1657                        if 'PWDR' in hist[:4]: 
1658                            Histograms[hist] = self.GetPWDRdatafromTree(item)
1659                        elif 'HKLF' in hist[:4]:
1660                            Histograms[hist] = self.GetHKLFdatafromTree(item)
1661                        #future restraint, etc. histograms here           
1662                        Histograms[hist]['hId'] = hId
1663                        hId += 1
1664        return Histograms,Phases
1665       
1666    class ViewParmDialog(wx.Dialog):
1667        def __init__(self,parent,title,parmDict):
1668            wx.Dialog.__init__(self,parent,-1,title,size=(300,430),
1669                pos=wx.DefaultPosition,style=wx.DEFAULT_DIALOG_STYLE)
1670            panel = wx.Panel(self,size=(300,430))
1671            parmNames = parmDict.keys()
1672            parmNames.sort()
1673            parmText = ' p:h:Parameter       refine?              value\n'
1674            for name in parmNames:
1675                parmData = parmDict[name]
1676                try:
1677                    parmText += ' %s \t%12.4g \n'%(name.ljust(19)+'\t'+parmData[1],parmData[0])
1678                except TypeError:
1679                    pass
1680            parmTable = wx.TextCtrl(panel,-1,parmText,
1681                style=wx.TE_MULTILINE|wx.TE_READONLY,size=(290,400))
1682            mainSizer = wx.BoxSizer(wx.VERTICAL)
1683            mainSizer.Add(parmTable)
1684            panel.SetSizer(mainSizer)
1685                           
1686    def OnViewLSParms(self,event):
1687        parmDict = {}
1688        Histograms,Phases = self.GetUsedHistogramsAndPhasesfromTree()
1689        Natoms,phaseVary,phaseDict,pawleyLookup,FFtable,BLtable = G2str.GetPhaseData(Phases,Print=False)       
1690        hapVary,hapDict,controlDict = G2str.GetHistogramPhaseData(Phases,Histograms,Print=False)
1691        histVary,histDict,controlDict = G2str.GetHistogramData(Histograms,Print=False)
1692        varyList = phaseVary+hapVary+histVary
1693        parmDict.update(phaseDict)
1694        parmDict.update(hapDict)
1695        parmDict.update(histDict)
1696        for parm in parmDict:
1697            if parm.split(':')[-1] in ['Azimuth','Gonio. radius','Lam1','Lam2','Omega','Chi','Phi']:
1698                parmDict[parm] = [parmDict[parm],' ']
1699            elif parm.split(':')[-2] in ['Ax','Ay','Az','SHmodel','SHord']:
1700                parmDict[parm] = [parmDict[parm],' ']
1701            elif parm in varyList:
1702                parmDict[parm] = [parmDict[parm],'True']
1703            else:
1704                parmDict[parm] = [parmDict[parm],'False']
1705        parmDict[' Num refined'] = [len(varyList),'']
1706        dlg = self.ViewParmDialog(self,'Parameters for least squares',parmDict)
1707        try:
1708            if dlg.ShowModal() == wx.ID_OK:
1709                print 'do something with changes?? - No!'
1710        finally:
1711            dlg.Destroy()
1712       
1713    def OnRefine(self,event):
1714        self.OnFileSave(event)
1715        # check that constraints are OK here
1716        errmsg, warnmsg = G2str.CheckConstraints(self.GSASprojectfile)
1717        if errmsg:
1718            print('Error in constraints:\n'+errmsg+
1719                  '\nRefinement not possible')
1720            self.ErrorDialog('Constraint Error',
1721                             'Error in constraints:\n'+errmsg+
1722                             '\nRefinement not possible')
1723            return
1724        if warnmsg:
1725            print('Conflict between refinment flag settings and constraints:\n'+
1726                  warnmsg+'\nRefinement not possible')
1727            self.ErrorDialog('Refinement Flag Error',
1728                             'Conflict between refinment flag settings and constraints:\n'+
1729                             warnmsg+
1730                             '\nRefinement not possible')
1731            return
1732        #works - but it'd be better if it could restore plots
1733        dlg = wx.ProgressDialog('Residual','Powder profile Rwp =',101.0, 
1734            style = wx.PD_ELAPSED_TIME|wx.PD_AUTO_HIDE|wx.PD_CAN_ABORT)
1735        screenSize = wx.ClientDisplayRect()
1736        Size = dlg.GetSize()
1737        Size = (int(Size[0]*1.2),Size[1]) # increase size a bit along x
1738        dlg.SetPosition(wx.Point(screenSize[2]-Size[0]-305,screenSize[1]+5))
1739        dlg.SetSize(Size)
1740        Rwp = 100.00
1741        try:
1742            Rwp = G2str.Refine(self.GSASprojectfile,dlg)
1743        finally:
1744            dlg.Destroy()       
1745        dlg = wx.MessageDialog(self,'Load new result?','Refinement results, Rwp =%.3f'%(Rwp),wx.OK|wx.CANCEL)
1746        try:
1747            if dlg.ShowModal() == wx.ID_OK:
1748                Id = 0
1749                self.PatternTree.DeleteChildren(self.root)
1750                if self.HKL: self.HKL = []
1751                if self.G2plotNB.plotList:
1752                    self.G2plotNB.clear()
1753                G2IO.ProjFileOpen(self)
1754                item, cookie = self.PatternTree.GetFirstChild(self.root)
1755                while item and not Id:
1756                    name = self.PatternTree.GetItemText(item)
1757                    if name[:4] in ['PWDR','HKLF']:
1758                        Id = item
1759                    item, cookie = self.PatternTree.GetNextChild(self.root, cookie)               
1760                if Id:
1761                    self.PatternTree.SelectItem(Id)
1762        finally:
1763            dlg.Destroy()
1764
1765    def OnSeqRefine(self,event):
1766        Id = G2gd.GetPatternTreeItemId(self,self.root,'Sequental results')
1767        if not Id:
1768            Id = self.PatternTree.AppendItem(self.root,text='Sequental results')
1769            self.PatternTree.SetItemPyData(Id,{})           
1770        self.OnFileSave(event)
1771        # check that constraints are OK here
1772        errmsg, warnmsg = G2str.CheckConstraints(self.GSASprojectfile)
1773        if errmsg:
1774            print('Error in constraints:\n'+errmsg+
1775                  '\nRefinement not possible')
1776            self.ErrorDialog('Constraint Error',
1777                             'Error in constraints:\n'+errmsg+
1778                             '\nRefinement not possible')
1779            return
1780        if warnmsg:
1781            print('Conflict between refinment flag settings and constraints:\n'+
1782                  warnmsg+'\nRefinement not possible')
1783            self.ErrorDialog('Refinement Flag Error',
1784                             'Conflict between refinment flag settings and constraints:\n'+
1785                             warnmsg+'\nRefinement not possible')
1786            return
1787        dlg = wx.ProgressDialog('Residual for histogram 0','Powder profile Rwp =',101.0, 
1788            style = wx.PD_ELAPSED_TIME|wx.PD_AUTO_HIDE|wx.PD_CAN_ABORT)
1789        screenSize = wx.ClientDisplayRect()
1790        Size = dlg.GetSize()
1791        Size = (int(Size[0]*1.2),Size[1]) # increase size a bit along x
1792        dlg.SetPosition(wx.Point(screenSize[2]-Size[0]-305,screenSize[1]+5))
1793        dlg.SetSize(Size)
1794        try:
1795            G2str.SeqRefine(self.GSASprojectfile,dlg)
1796        finally:
1797            dlg.Destroy()       
1798        dlg = wx.MessageDialog(self,'Load new result?','Refinement results',wx.OK|wx.CANCEL)
1799        try:
1800            if dlg.ShowModal() == wx.ID_OK:
1801                Id = 0
1802                self.PatternTree.DeleteChildren(self.root)
1803                if self.HKL: self.HKL = []
1804                if self.G2plotNB.plotList:
1805                    self.G2plotNB.clear()
1806                G2IO.ProjFileOpen(self)
1807                item, cookie = self.PatternTree.GetFirstChild(self.root)
1808                while item and not Id:
1809                    name = self.PatternTree.GetItemText(item)
1810                    if name[:4] in ['PWDR','HKLF']:
1811                        Id = item
1812                    item, cookie = self.PatternTree.GetNextChild(self.root, cookie)               
1813                if Id:
1814                    self.PatternTree.SelectItem(Id)
1815        finally:
1816            dlg.Destroy()
1817       
1818    def ErrorDialog(self,title,message,parent=None, wtype=wx.OK):
1819        result = None
1820        if parent is None:
1821            dlg = wx.MessageDialog(self, message, title,  wtype)
1822        else:
1823            dlg = wx.MessageDialog(parent, message, title,  wtype)
1824            dlg.CenterOnParent() # not working on Mac
1825        try:
1826            result = dlg.ShowModal()
1827        finally:
1828            dlg.Destroy()
1829        return result
1830
1831class GSASIImain(wx.App):
1832    def OnInit(self):
1833        self.main = GSASII(None)
1834        self.main.Show()
1835        self.SetTopWindow(self.main)
1836        return True
1837
1838def main():
1839    application = GSASIImain(0)
1840    if wxInspector: wxeye.InspectionTool().Show()
1841
1842    #application.main.OnRefine(None)
1843    application.MainLoop()
1844   
1845if __name__ == '__main__':
1846    main()
Note: See TracBrowser for help on using the repository browser.