source: trunk/GSASII.py @ 686

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

add restraints to GSASIIstruct.py - input & printing only
no calcs yet

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