source: trunk/GSASII.py @ 616

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

clean up default instrument parameters

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