source: trunk/GSASII.py @ 636

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

remove self.PWDR - not used
remove phase data plots & cell refine flag for only HKLF data
implement refine Jacobian for HKLF data - still needs refine Hessian

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