source: trunk/GSASII.py @ 630

Last change on this file since 630 was 630, checked in by vondreele, 13 years ago

major mods for HKLF data
remove some dead code
mark more code as dead (#)
implement cif data style as 'val(esd)' for f & f_squared
continue implementation of HKLF data in refinement
HKLF now OK in Fourier & charge flip calcs.

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