source: trunk/GSASII.py @ 623

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

remove powder read from Data menu
remove 'menu' from import menus
use longFormatName as help for import menu items
remove _init_coll_Import_Items
added updateHKLFdata to process HKLF data sets

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