source: trunk/GSASII.py @ 618

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

tweak import menus and only show ASCII input

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