source: trunk/GSASII.py @ 620

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

remove excessive tabs in source code
fix HKL controls GUI
change HKL reflection record to match the PWDR one
start getting HKLF into fourier & charge flip

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