source: trunk/GSASII.py @ 580

Last change on this file since 580 was 580, checked in by toby, 11 years ago

finish import structure factor; refactor import classes

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