source: trunk/GSASII.py @ 614

Last change on this file since 614 was 614, checked in by toby, 10 years ago

import GSAS powder data tested; import routines moved to imports

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