source: trunk/GSASII.py @ 619

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

tweak import more

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