source: trunk/GSASII.py @ 687

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

histogram wtFactors for PWDR & HKLF (latter not implemented yet)
means that data[0] is now {'wtFactor':1.0} instead of a mostly unused file name
also put in atomIndx for doing restraint calcs.

  • Property svn:keywords set to Date Author Revision URL Id
File size: 104.3 KB
Line 
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3#GSASII
4########### SVN repository information ###################
5# $Date: 2012-07-12 20:10:16 +0000 (Thu, 12 Jul 2012) $
6# $Author: vondreele $
7# $Revision: 687 $
8# $URL: trunk/GSASII.py $
9# $Id: GSASII.py 687 2012-07-12 20:10:16Z 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: 687 $")
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,[{'wtFactor':1.0},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(Id,[{'wtFactor':1.0},rd.powderdata])
758            self.PatternTree.SetItemPyData(
759                self.PatternTree.AppendItem(Id,text='Comments'),
760                rd.comments)
761            Tmin = min(rd.powderdata[0])
762            Tmax = max(rd.powderdata[0])
763            self.PatternTree.SetItemPyData(
764                self.PatternTree.AppendItem(Id,text='Limits'),
765                [(Tmin,Tmax),[Tmin,Tmax]])
766            self.PatternId = G2gd.GetPatternTreeItemId(self,Id,'Limits')
767            self.PatternTree.SetItemPyData(
768                self.PatternTree.AppendItem(Id,text='Background'),
769                [['chebyschev',True,3,1.0,0.0,0.0],
770                 {'nDebye':0,'debyeTerms':[],'nPeaks':0,'peaksList':[]}])
771            self.PatternTree.SetItemPyData(
772                self.PatternTree.AppendItem(Id,text='Instrument Parameters'),
773                self.SetPowderInstParms(Iparm,rd))
774            self.PatternTree.SetItemPyData(
775                self.PatternTree.AppendItem(Id,text='Sample Parameters'),
776                rd.Sample)
777            self.PatternTree.SetItemPyData(
778                self.PatternTree.AppendItem(Id,text='Peak List')
779                ,[])
780            self.PatternTree.SetItemPyData(
781                self.PatternTree.AppendItem(Id,text='Index Peak List'),
782                [])
783            self.PatternTree.SetItemPyData(
784                self.PatternTree.AppendItem(Id,text='Unit Cells List'),
785                [])
786            self.PatternTree.SetItemPyData(
787                self.PatternTree.AppendItem(Id,text='Reflection Lists'),
788                {})
789            self.PatternTree.Expand(Id)
790        self.PatternTree.SelectItem(Id)
791        return # success
792
793    def _init_Exports(self,parent):
794        '''
795        '''
796#        submenu = wx.Menu()
797#        item = parent.AppendMenu(
798#            wx.ID_ANY, 'entire project',
799#            submenu, help='Export entire project')
800#        item = submenu.Append(
801#            wx.ID_ANY,
802#            help='this is a module for testing',
803#            kind=wx.ITEM_NORMAL,
804#            text='to test file')
805#        self.Bind(wx.EVT_MENU, self.OnExportTest, id=item.GetId())
806#        import G2export
807#    def OnExportTest(self,event):
808#        import G2export
809#        reload(G2export)
810#        G2export.ProjExport(self)
811
812    def _init_coll_Export_Items(self,parent):
813        self.ExportPattern = parent.Append(help='Select PWDR item to enable',id=wxID_EXPORTPATTERN, kind=wx.ITEM_NORMAL,
814            text='Export Powder Patterns...')
815        self.ExportPeakList = parent.Append(help='',id=wxID_EXPORTPEAKLIST, kind=wx.ITEM_NORMAL,
816            text='Export All Peak Lists...')
817        self.ExportHKL = parent.Append(help='',id=wxID_EXPORTHKL, kind=wx.ITEM_NORMAL,
818            text='Export HKLs...')
819        self.ExportPDF = parent.Append(help='Select PDF item to enable',id=wxID_EXPORTPDF, kind=wx.ITEM_NORMAL,
820            text='Export PDF...')
821        self.ExportPhase = parent.Append(help='',id=wxID_EXPORTPHASE, kind=wx.ITEM_NORMAL,
822            text='Export Phase...')
823        self.ExportCIF = parent.Append(help='',id=wxID_EXPORTCIF, kind=wx.ITEM_NORMAL,
824            text='Export CIF...')
825        self.ExportPattern.Enable(False)
826        self.ExportPeakList.Enable(True)
827        self.ExportHKL.Enable(False)
828        self.ExportPDF.Enable(False)
829        self.ExportPhase.Enable(False)
830        self.ExportCIF.Enable(False)
831        self.Bind(wx.EVT_MENU, self.OnExportPatterns, id=wxID_EXPORTPATTERN)
832        self.Bind(wx.EVT_MENU, self.OnExportPeakList, id=wxID_EXPORTPEAKLIST)
833        self.Bind(wx.EVT_MENU, self.OnExportHKL, id=wxID_EXPORTHKL)
834        self.Bind(wx.EVT_MENU, self.OnExportPDF, id=wxID_EXPORTPDF)
835        self.Bind(wx.EVT_MENU, self.OnExportPhase, id=wxID_EXPORTPHASE)
836        self.Bind(wx.EVT_MENU, self.OnExportCIF, id=wxID_EXPORTCIF)
837               
838    def _init_utils(self):
839        self.GSASIIMenu = wx.MenuBar()
840        self.File = wx.Menu(title='')
841        self.Data = wx.Menu(title='')       
842        self.Calculate = wx.Menu(title='')       
843        self.Import = wx.Menu(title='')       
844        self.Export = wx.Menu(title='')       
845
846        self._init_coll_GSASIIMenu_Menus(self.GSASIIMenu)
847        self._init_coll_File_Items(self.File)
848        self._init_coll_Data_Items(self.Data)
849        self._init_coll_Calculate_Items(self.Calculate)
850        self.ImportMenuId = {}
851        self._init_Import_Phase(self.Import)
852        self._init_Import_powder(self.Import)
853        self._init_Import_Sfact(self.Import)
854        self._init_coll_Export_Items(self.Export)
855        self._init_Exports(self.Export)
856       
857    def _init_ctrls(self, parent):
858        wx.Frame.__init__(self, name='GSASII', parent=parent,
859            size=wx.Size(400, 250),style=wx.DEFAULT_FRAME_STYLE, title='GSAS-II data tree')
860        clientSize = wx.ClientDisplayRect()
861        Size = self.GetSize()
862        xPos = clientSize[2]-Size[0]
863        self.SetPosition(wx.Point(xPos,clientSize[1]))
864        self._init_utils()
865        self.SetMenuBar(self.GSASIIMenu)
866        self.Bind(wx.EVT_SIZE, self.OnSize)
867        self.CreateStatusBar()
868        self.mainPanel = wx.Panel(self,-1)
869       
870        self.PatternTree = wx.TreeCtrl(id=wxID_PATTERNTREE,
871            parent=self.mainPanel, pos=wx.Point(0, 0),style=wx.TR_DEFAULT_STYLE )
872        self.PatternTree.Bind(wx.EVT_TREE_SEL_CHANGED,
873            self.OnPatternTreeSelChanged, id=wxID_PATTERNTREE)
874        self.PatternTree.Bind(wx.EVT_TREE_ITEM_COLLAPSED,
875            self.OnPatternTreeItemCollapsed, id=wxID_PATTERNTREE)
876        self.PatternTree.Bind(wx.EVT_TREE_ITEM_EXPANDED,
877            self.OnPatternTreeItemExpanded, id=wxID_PATTERNTREE)
878        self.PatternTree.Bind(wx.EVT_TREE_DELETE_ITEM,
879            self.OnPatternTreeItemDelete, id=wxID_PATTERNTREE)
880        self.PatternTree.Bind(wx.EVT_TREE_KEY_DOWN,
881            self.OnPatternTreeKeyDown, id=wxID_PATTERNTREE)
882        self.root = self.PatternTree.AddRoot('Loaded Data: ')
883       
884        plotFrame = wx.Frame(None,-1,'GSASII Plots',size=wx.Size(700,600), \
885            style=wx.DEFAULT_FRAME_STYLE ^ wx.CLOSE_BOX)
886        self.G2plotNB = G2plt.G2PlotNoteBook(plotFrame)
887        plotFrame.Show()
888       
889        self.dataDisplay = None
890       
891    def __init__(self, parent):
892        self._init_ctrls(parent)
893        self.Bind(wx.EVT_CLOSE, self.ExitMain)
894        # various defaults
895        self.oldFocus = None
896        self.GSASprojectfile = ''
897        self.dirname = os.path.expanduser('~')       #start in the users home directory by default; may be meaningless
898        self.undofile = ''
899        self.TreeItemDelete = False
900        self.Offset = [0.0,0.0]
901        self.delOffset = .02
902        self.refOffset = -100.0
903        self.refDelt = .01
904        self.Weight = False
905        self.IparmName = ''  # to be removed when SelectPowderData & GetInstrumentFile is
906        self.IfPlot = False
907        self.PatternId = 0
908        self.PickId = 0
909        self.PeakTable = []
910        self.LimitsTable = []
911        self.HKL = []
912        self.Lines = []
913        self.itemPicked = None
914        self.dataFrame = None
915        self.Interpolate = 'nearest'
916        self.ContourColor = 'Paired'
917        self.VcovColor = 'RdYlGn'
918        self.Projection = 'equal area'
919        self.logPlot = False
920        self.qPlot = False
921        self.Contour = False
922        self.Legend = False
923        self.SinglePlot = False
924        self.plotView = 0
925        self.Image = 0
926        self.oldImagefile = ''
927        self.ImageZ = []
928        self.Integrate = 0
929        self.imageDefault = {}
930        self.Sngl = 0
931        self.ifGetRing = False
932        self.setPoly = False
933        arg = sys.argv
934        if len(arg) > 1:
935            self.GSASprojectfile = arg[1]
936            self.dirname = os.path.dirname(arg[1])
937            if self.dirname: os.chdir(self.dirname)
938            G2IO.ProjFileOpen(self)
939            self.PatternTree.Expand(self.root)
940            self.Refine.Enable(True)
941            self.SeqRefine.Enable(True)
942
943    def OnSize(self,event):
944        w,h = self.GetClientSizeTuple()
945        self.mainPanel.SetSize(wx.Size(w,h))
946        self.PatternTree.SetSize(wx.Size(w,h))
947                       
948    def OnPatternTreeSelChanged(self, event):
949        if self.TreeItemDelete:
950            self.TreeItemDelete = False
951        else:
952            pltNum = self.G2plotNB.nb.GetSelection()
953            if pltNum >= 0:                         #to avoid the startup with no plot!
954                pltPage = self.G2plotNB.nb.GetPage(pltNum)
955                pltPlot = pltPage.figure
956            item = event.GetItem()
957            G2gd.MovePatternTreeToGrid(self,item)
958            if self.oldFocus:
959                self.oldFocus.SetFocus()
960       
961    def OnPatternTreeItemCollapsed(self, event):
962        event.Skip()
963
964    def OnPatternTreeItemExpanded(self, event):
965        event.Skip()
966       
967    def OnPatternTreeItemDelete(self, event):
968        self.TreeItemDelete = True
969
970    def OnPatternTreeItemActivated(self, event):
971        event.Skip()
972       
973    def OnPatternTreeKeyDown(self,event):
974        key = event.GetKeyCode()
975        item = self.PickId
976        if type(item) is int: return # is this the toplevel in tree?
977        if key == wx.WXK_UP:
978            self.oldFocus = wx.Window.FindFocus()
979            self.PatternTree.GetPrevSibling(item)
980        elif key == wx.WXK_DOWN:
981            self.oldFocus = wx.Window.FindFocus()
982            self.PatternTree.GetNextSibling(item)
983               
984    def OnPwdrRead(self, event):
985        self.CheckNotebook()
986        dlg = wx.FileDialog(self, 'Choose files', '.', '', 
987            'GSAS fxye files (*.fxye)|*.fxye|GSAS fxy files (*.fxy)|*.fxy|Topas xye files (*.xye)|*.xye|All files (*.*)|*.*', 
988            wx.OPEN | wx.MULTIPLE | wx.CHANGE_DIR)
989        try:
990            if dlg.ShowModal() == wx.ID_OK:
991                filenames = dlg.GetPaths()
992                filenames.sort()
993                for filename in filenames:
994                    Data,Iparm,Comments,Temperature = G2IO.SelectPowderData(self, filename)              #Data: list of tuples (filename,Pos,Bank)
995                    if not Data:                                                    #if Data rejected by user - go to next one
996                        continue
997                    DataType = Iparm['INS   HTYPE ']                                #expect only 4 char string
998                    DataType = DataType.strip()[0:3]                                #just 1st 3 chars
999                    wx.BeginBusyCursor()
1000                    Sample = G2pdG.SetDefaultSample()
1001                    Sample['Temperature'] = Temperature
1002                    try:
1003                        for Item in Data:
1004                            vals = Item[2].split()          #split up the BANK record
1005                            Id = self.PatternTree.AppendItem(parent=self.root,text='PWDR '+os.path.basename(Item[0])+': '+vals[0]+vals[1])
1006                            data = G2IO.GetPowderData(filename,Item[1],Item[2],DataType)
1007                            self.PatternTree.SetItemPyData(Id,[Item,data])
1008                            '''
1009                            Each tree item data is a list with:
1010                            Item: the (filename,Pos,Bank) tuple
1011                            data: (x,y,w,yc,yb,yd) list  of np.arrays from GetPowderData
1012                            '''
1013                           
1014                            self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Comments'),Comments)                           
1015                            Tmin = min(data[0])
1016                            Tmax = max(data[0])
1017                            self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Limits'),[(Tmin,Tmax),[Tmin,Tmax]])
1018                            self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Background'),[['chebyschev',True,3,1.0,0.0,0.0],
1019                                {'nDebye':0,'debyeTerms':[],'nPeaks':0,'peaksList':[]}])
1020       
1021                            data = [DataType,]
1022                            if 'C' in DataType:
1023                                s = Iparm['INS  1 ICONS']
1024                                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
1025                                if not v[1]:
1026                                    names = ['Type','Lam','Zero','Polariz.','U','V','W','X','Y','SH/L','Azimuth'] 
1027                                    v = (v[0],v[2],v[4])
1028                                    codes = [0,0,0,0]
1029                                    Sample['Type'] = 'Debye-Scherrer'               #default instrument type
1030                                else:
1031                                    names = ['Type','Lam1','Lam2','Zero','I(L2)/I(L1)','Polariz.','U','V','W','X','Y','SH/L','Azimuth']
1032                                    codes = [0,0,0,0,0,0]
1033                                    Sample['Type'] = 'Bragg-Brentano'               #default instrument type
1034                                    Sample['Shift'] = [0.0,False]
1035                                    Sample['Transparency'] = [0.0,False]
1036                                data.extend(v)
1037                                v1 = Iparm['INS  1PRCF1 '].split()                                                 
1038                                v = Iparm['INS  1PRCF11'].split()
1039                                data.extend([float(v[0]),float(v[1]),float(v[2])])                  #get GU, GV & GW - always here
1040                                try:
1041                                    azm = float(Iparm['INS  1DETAZM'])
1042                                except KeyError:                                                #not in this Iparm file
1043                                    azm = 0.0
1044                                v = Iparm['INS  1PRCF12'].split()
1045                                if v1[0] == '3':
1046                                    data.extend([float(v[0]),float(v[1]),float(v[2])+float(v[3]),azm])  #get LX, LY, S+H/L & azimuth
1047                                else:
1048                                    data.extend([0.0,0.0,0.002,azm])                                      #OK defaults if fxn #3 not 1st in iprm file
1049                                codes.extend([0,0,0,0,0,0,0])
1050                            self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Instrument Parameters'),[tuple(data),data,codes,names])
1051                            self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Sample Parameters'),Sample)
1052                            self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Peak List'),[])
1053                            self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Index Peak List'),[])
1054                            self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Unit Cells List'),[])
1055                            self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Reflection Lists'),{})             
1056                            self.PatternId = G2gd.GetPatternTreeItemId(self,Id,'Limits')
1057                    finally:
1058                        wx.EndBusyCursor()
1059                self.PatternTree.Expand(Id)
1060                self.PatternTree.SelectItem(Id)
1061   
1062        finally:
1063            dlg.Destroy()
1064       
1065    def OnReadPowderPeaks(self,event):
1066        Cuka = 1.54052
1067        self.CheckNotebook()
1068        dlg = wx.FileDialog(self, 'Choose file with peak list', '.', '', 
1069            'peak files (*.txt)|*.txt|All files (*.*)|*.*',wx.OPEN|wx.CHANGE_DIR)
1070        try:
1071            if dlg.ShowModal() == wx.ID_OK:
1072                self.HKL = []
1073                self.powderfile = dlg.GetPath()
1074                comments,peaks = G2IO.GetPowderPeaks(self.powderfile)
1075                Id = self.PatternTree.AppendItem(parent=self.root,text='PKS '+os.path.basename(self.powderfile))
1076                data = ['PKS',Cuka,0.0]
1077                names = ['Type','Lam','Zero'] 
1078                codes = [0,0]
1079                self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Instrument Parameters'),[tuple(data),data,codes,names])
1080                self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Comments'),comments)
1081                self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Index Peak List'),peaks)
1082                self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Unit Cells List'),[])             
1083                self.PatternTree.Expand(Id)
1084                self.PatternTree.SelectItem(Id)
1085        finally:
1086            dlg.Destroy()
1087           
1088    def OnImageRead(self,event):
1089        self.CheckNotebook()
1090        dlg = wx.FileDialog(
1091            self, 'Choose image files', '.', '',
1092            'Any image file (*.tif;*.tiff;*.mar*;*.avg;*.sum;*.img;*.G2img)|'
1093            '*.tif;*.tiff;*.mar*;*.avg;*.sum;*.img;*.G2img;*.zip|'
1094            'Any detector tif (*.tif;*.tiff)|*.tif;*.tiff|'
1095            'MAR file (*.mar*)|*.mar*|'
1096            'GE Image (*.avg;*.sum)|*.avg;*.sum|'
1097            'ADSC Image (*.img)|*.img|'
1098            'GSAS-II Image (*.G2img)|*.G2img|'
1099            'Zip archive (*.zip)|*.zip|'
1100            'All files (*.*)|*.*',
1101            wx.OPEN | wx.MULTIPLE|wx.CHANGE_DIR)
1102        try:
1103            if dlg.ShowModal() == wx.ID_OK:
1104                imagefiles = dlg.GetPaths()
1105                imagefiles.sort()
1106                for imagefile in imagefiles:
1107                    # if a zip file, open and extract
1108                    if os.path.splitext(imagefile)[1].lower() == '.zip':
1109                        extractedfile = G2IO.ExtractFileFromZip(imagefile,parent=self)
1110                        if extractedfile is not None and extractedfile != imagefile:
1111                            imagefile = extractedfile
1112                    Comments,Data,Npix,Image = G2IO.GetImageData(self,imagefile)
1113                    if Comments:
1114                        Id = self.PatternTree.AppendItem(parent=self.root,text='IMG '+os.path.basename(imagefile))
1115                        self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Comments'),Comments)
1116                        Imax = np.amax(Image)
1117                        Imin = max(0.0,np.amin(Image))          #force positive
1118                        if self.imageDefault:
1119                            Data = copy.copy(self.imageDefault)
1120                            Data['showLines'] = True
1121                            Data['ring'] = []
1122                            Data['rings'] = []
1123                            Data['cutoff'] = 10
1124                            Data['pixLimit'] = 20
1125                            Data['edgemin'] = 100000000
1126                            Data['calibdmin'] = 0.5
1127                            Data['calibskip'] = 0
1128                            Data['ellipses'] = []
1129                            Data['calibrant'] = ''
1130                        else:
1131                            Data['type'] = 'PWDR'
1132                            Data['color'] = 'Paired'
1133                            Data['tilt'] = 0.0
1134                            Data['rotation'] = 0.0
1135                            Data['showLines'] = False
1136                            Data['ring'] = []
1137                            Data['rings'] = []
1138                            Data['cutoff'] = 10
1139                            Data['pixLimit'] = 20
1140                            Data['calibdmin'] = 0.5
1141                            Data['calibskip'] = 0
1142                            Data['edgemin'] = 100000000
1143                            Data['ellipses'] = []
1144                            Data['calibrant'] = ''
1145                            Data['IOtth'] = [2.0,5.0]
1146                            Data['LRazimuth'] = [135,225]
1147                            Data['azmthOff'] = 0.0
1148                            Data['outChannels'] = 2500
1149                            Data['outAzimuths'] = 1
1150                            Data['centerAzm'] = False
1151                            Data['fullIntegrate'] = False
1152                            Data['setRings'] = False
1153                            Data['background image'] = ['',1.0]                           
1154                        Data['setDefault'] = False
1155                        Data['range'] = [(Imin,Imax),[Imin,Imax]]
1156                        self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Image Controls'),Data)
1157                        Masks = {'Points':[],'Rings':[],'Arcs':[],'Polygons':[],'Thresholds':[(Imin,Imax),[Imin,Imax]]}
1158                        self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Masks'),Masks)
1159                        self.PatternTree.SetItemPyData(Id,[Npix,imagefile])
1160                        self.PickId = Id
1161                        self.Image = Id
1162                self.PatternTree.SelectItem(G2gd.GetPatternTreeItemId(self,Id,'Image Controls'))             #show last one
1163        finally:
1164            dlg.Destroy()
1165
1166    def CheckNotebook(self):
1167        '''Make sure the data tree has the minimally expected controls
1168        (BHT) correct?
1169        '''
1170        if not G2gd.GetPatternTreeItemId(self,self.root,'Notebook'):
1171            sub = self.PatternTree.AppendItem(parent=self.root,text='Notebook')
1172            self.PatternTree.SetItemPyData(sub,[''])
1173        if not G2gd.GetPatternTreeItemId(self,self.root,'Controls'):
1174            sub = self.PatternTree.AppendItem(parent=self.root,text='Controls')
1175            self.PatternTree.SetItemPyData(sub,{})
1176        if not G2gd.GetPatternTreeItemId(self,self.root,'Covariance'):
1177            sub = self.PatternTree.AppendItem(parent=self.root,text='Covariance')
1178            self.PatternTree.SetItemPyData(sub,{})
1179        if not G2gd.GetPatternTreeItemId(self,self.root,'Constraints'):
1180            sub = self.PatternTree.AppendItem(parent=self.root,text='Constraints')
1181            self.PatternTree.SetItemPyData(sub,{'Hist':[],'HAP':[],'Phase':[]})
1182        if not G2gd.GetPatternTreeItemId(self,self.root,'Restraints'):
1183            sub = self.PatternTree.AppendItem(parent=self.root,text='Restraints')
1184            self.PatternTree.SetItemPyData(sub,{})
1185           
1186               
1187    class CopyDialog(wx.Dialog):
1188        def __init__(self,parent,title,text,data):
1189            wx.Dialog.__init__(self,parent,-1,title, 
1190                pos=wx.DefaultPosition,style=wx.DEFAULT_DIALOG_STYLE)
1191            self.data = data
1192            panel = wx.Panel(self)
1193            mainSizer = wx.BoxSizer(wx.VERTICAL)
1194            topLabl = wx.StaticText(panel,-1,text)
1195            mainSizer.Add((10,10),1)
1196            mainSizer.Add(topLabl,0,wx.ALIGN_CENTER_VERTICAL|wx.LEFT,10)
1197            mainSizer.Add((10,10),1)
1198            ncols = len(data)/40+1
1199            dataGridSizer = wx.FlexGridSizer(rows=len(data),cols=ncols,hgap=2,vgap=2)
1200            for id,item in enumerate(self.data):
1201                ckbox = wx.CheckBox(panel,id,item[1])
1202                ckbox.Bind(wx.EVT_CHECKBOX,self.OnCopyChange)                   
1203                dataGridSizer.Add(ckbox,0,wx.LEFT,10)
1204            mainSizer.Add(dataGridSizer,0,wx.EXPAND)
1205            OkBtn = wx.Button(panel,-1,"Ok")
1206            OkBtn.Bind(wx.EVT_BUTTON, self.OnOk)
1207            cancelBtn = wx.Button(panel,-1,"Cancel")
1208            cancelBtn.Bind(wx.EVT_BUTTON, self.OnCancel)
1209            btnSizer = wx.BoxSizer(wx.HORIZONTAL)
1210            btnSizer.Add((20,20),1)
1211            btnSizer.Add(OkBtn)
1212            btnSizer.Add((20,20),1)
1213            btnSizer.Add(cancelBtn)
1214            btnSizer.Add((20,20),1)
1215           
1216            mainSizer.Add(btnSizer,0,wx.EXPAND|wx.BOTTOM|wx.TOP, 10)
1217            panel.SetSizer(mainSizer)
1218            panel.Fit()
1219            self.Fit()
1220       
1221        def OnCopyChange(self,event):
1222            id = event.GetId()
1223            self.data[id][0] = self.FindWindowById(id).GetValue()       
1224           
1225        def OnOk(self,event):
1226            parent = self.GetParent()
1227            parent.Raise()
1228            self.EndModal(wx.ID_OK)             
1229           
1230        def OnCancel(self,event):
1231            parent = self.GetParent()
1232            parent.Raise()
1233            self.EndModal(wx.ID_CANCEL)             
1234           
1235        def GetData(self):
1236            return self.data
1237       
1238    class SumDialog(wx.Dialog):
1239        def __init__(self,parent,title,text,dataType,data):
1240            wx.Dialog.__init__(self,parent,-1,title, 
1241                pos=wx.DefaultPosition,style=wx.DEFAULT_DIALOG_STYLE)
1242            self.data = data
1243            panel = wx.Panel(self)
1244            mainSizer = wx.BoxSizer(wx.VERTICAL)
1245            topLabl = wx.StaticText(panel,-1,text)
1246            mainSizer.Add((10,10),1)
1247            mainSizer.Add(topLabl,0,wx.ALIGN_CENTER_VERTICAL|wx.LEFT,10)
1248            mainSizer.Add((10,10),1)
1249            dataGridSizer = wx.FlexGridSizer(rows=len(data),cols=2,hgap=2,vgap=2)
1250            for id,item in enumerate(self.data[:-1]):
1251                name = wx.TextCtrl(panel,-1,item[1],size=wx.Size(200,20))
1252                name.SetEditable(False)
1253                scale = wx.TextCtrl(panel,id,'%.3f'%(item[0]),style=wx.TE_PROCESS_ENTER)
1254                scale.Bind(wx.EVT_TEXT_ENTER,self.OnScaleChange)
1255                scale.Bind(wx.EVT_KILL_FOCUS,self.OnScaleChange)
1256                dataGridSizer.Add(scale,0,wx.LEFT,10)
1257                dataGridSizer.Add(name,0,wx.RIGHT,10)
1258            if dataType:
1259                dataGridSizer.Add(wx.StaticText(panel,-1,'Sum result name: '+dataType),0, \
1260                    wx.LEFT|wx.TOP|wx.ALIGN_CENTER_VERTICAL,10)
1261                self.name = wx.TextCtrl(panel,-1,self.data[-1],size=wx.Size(200,20),style=wx.TE_PROCESS_ENTER)
1262                self.name.Bind(wx.EVT_TEXT_ENTER,self.OnNameChange)
1263                self.name.Bind(wx.EVT_KILL_FOCUS,self.OnNameChange)
1264                dataGridSizer.Add(self.name,0,wx.RIGHT|wx.TOP,10)
1265            mainSizer.Add(dataGridSizer,0,wx.EXPAND)
1266            OkBtn = wx.Button(panel,-1,"Ok")
1267            OkBtn.Bind(wx.EVT_BUTTON, self.OnOk)
1268            cancelBtn = wx.Button(panel,-1,"Cancel")
1269            cancelBtn.Bind(wx.EVT_BUTTON, self.OnCancel)
1270            btnSizer = wx.BoxSizer(wx.HORIZONTAL)
1271            btnSizer.Add((20,20),1)
1272            btnSizer.Add(OkBtn)
1273            btnSizer.Add((20,20),1)
1274            btnSizer.Add(cancelBtn)
1275            btnSizer.Add((20,20),1)
1276           
1277            mainSizer.Add(btnSizer,0,wx.EXPAND|wx.BOTTOM|wx.TOP, 10)
1278            panel.SetSizer(mainSizer)
1279            panel.Fit()
1280            self.Fit()
1281
1282    class ConstraintDialog(wx.Dialog):
1283        '''Window to edit Constraint values
1284        '''
1285        def __init__(self,parent,title,text,data,separator='*'):
1286            wx.Dialog.__init__(self,parent,-1,title, 
1287                pos=wx.DefaultPosition,style=wx.DEFAULT_DIALOG_STYLE)
1288            self.data = data
1289            panel = wx.Panel(self)
1290            mainSizer = wx.BoxSizer(wx.VERTICAL)
1291            topLabl = wx.StaticText(panel,-1,text)
1292            mainSizer.Add((10,10),1)
1293            mainSizer.Add(topLabl,0,wx.ALIGN_CENTER_VERTICAL|wx.LEFT,10)
1294            mainSizer.Add((10,10),1)
1295            dataGridSizer = wx.FlexGridSizer(rows=len(data),cols=2,hgap=2,vgap=2)
1296            for id,item in enumerate(self.data[:-1]):
1297                lbl = item[1]
1298                if lbl[-1] != '=': lbl += ' ' + separator + ' '
1299                name = wx.StaticText(panel,-1,lbl,size=wx.Size(200,20),
1300                                     style=wx.ALIGN_RIGHT)
1301                scale = wx.TextCtrl(panel,id,'%.3f'%(item[0]),style=wx.TE_PROCESS_ENTER)
1302                scale.Bind(wx.EVT_TEXT_ENTER,self.OnScaleChange)
1303                scale.Bind(wx.EVT_KILL_FOCUS,self.OnScaleChange)
1304                dataGridSizer.Add(name,0,wx.LEFT,10)
1305                dataGridSizer.Add(scale,0,wx.RIGHT,10)
1306            mainSizer.Add(dataGridSizer,0,wx.EXPAND)
1307            OkBtn = wx.Button(panel,-1,"Ok")
1308            OkBtn.Bind(wx.EVT_BUTTON, self.OnOk)
1309            cancelBtn = wx.Button(panel,-1,"Cancel")
1310            cancelBtn.Bind(wx.EVT_BUTTON, self.OnCancel)
1311            btnSizer = wx.BoxSizer(wx.HORIZONTAL)
1312            btnSizer.Add((20,20),1)
1313            btnSizer.Add(OkBtn)
1314            btnSizer.Add((20,20),1)
1315            btnSizer.Add(cancelBtn)
1316            btnSizer.Add((20,20),1)
1317           
1318            mainSizer.Add(btnSizer,0,wx.EXPAND|wx.BOTTOM|wx.TOP, 10)
1319            panel.SetSizer(mainSizer)
1320            panel.Fit()
1321            self.Fit()
1322            self.CenterOnParent()
1323           
1324        def OnNameChange(self,event):
1325            self.data[-1] = self.name.GetValue() 
1326           
1327        def OnScaleChange(self,event):
1328            id = event.GetId()
1329            value = self.FindWindowById(id).GetValue()
1330            try:
1331                self.data[id][0] = float(value)
1332                self.FindWindowById(id).SetValue('%.3f'%(self.data[id][0]))
1333            except ValueError:
1334                if value and '-' not in value[0]:
1335                    print 'bad input - numbers only'
1336                    self.FindWindowById(id).SetValue('0.000')
1337           
1338        def OnOk(self,event):
1339            parent = self.GetParent()
1340            parent.Raise()
1341            self.EndModal(wx.ID_OK)             
1342           
1343        def OnCancel(self,event):
1344            parent = self.GetParent()
1345            parent.Raise()
1346            self.EndModal(wx.ID_CANCEL)             
1347           
1348        def GetData(self):
1349            return self.data
1350           
1351    def OnPwdrSum(self,event):
1352        TextList = []
1353        DataList = []
1354        SumList = []
1355        Names = []
1356        Inst = []
1357        SumItemList = []
1358        Comments = ['Sum equals: \n']
1359        if self.PatternTree.GetCount():
1360            item, cookie = self.PatternTree.GetFirstChild(self.root)
1361            while item:
1362                name = self.PatternTree.GetItemText(item)
1363                Names.append(name)
1364                if 'PWDR' in name:
1365                    TextList.append([0.0,name])
1366                    DataList.append(self.PatternTree.GetItemPyData(item)[1])    # (x,y,w,yc,yb,yd)
1367                    if not Inst:
1368                        Inst = self.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(self,item, 'Instrument Parameters'))
1369                item, cookie = self.PatternTree.GetNextChild(self.root, cookie)
1370            if len(TextList) < 2:
1371                self.ErrorDialog('Not enough data to sum','There must be more than one "PWDR" pattern')
1372                return
1373            TextList.append('default_sum_name')               
1374            dlg = self.SumDialog(self,'Sum data','Enter scale for each pattern in summation','PWDR',TextList)
1375            try:
1376                if dlg.ShowModal() == wx.ID_OK:
1377                    lenX = 0
1378                    Xminmax = [0,0]
1379                    Xsum = []
1380                    Ysum = []
1381                    Vsum = []
1382                    result = dlg.GetData()
1383                    for i,item in enumerate(result[:-1]):
1384                        scale,name = item
1385                        data = DataList[i]
1386                        if scale:
1387                            Comments.append("%10.3f %s" % (scale,' * '+name))
1388                            x,y,w,yc,yb,yd = data   #numpy arrays!
1389                            v = 1./w
1390                            if lenX:
1391                                if lenX != len(x):
1392                                    self.ErrorDialog('Data length error','Data to be summed must have same number of points'+ \
1393                                        '\nExpected:'+str(lenX)+ \
1394                                        '\nFound:   '+str(len(x))+'\nfor '+name)
1395                                    return
1396                            else:
1397                                lenX = len(x)
1398                            if Xminmax[1]:
1399                                if Xminmax != [x[0],x[-1]]:
1400                                    self.ErrorDialog('Data range error','Data to be summed must span same range'+ \
1401                                        '\nExpected:'+str(Xminmax[0])+' '+str(Xminmax[1])+ \
1402                                        '\nFound:   '+str(x[0])+' '+str(x[-1])+'\nfor '+name)
1403                                    return
1404                                else:
1405                                    for j,yi in enumerate(y):
1406                                         Ysum[j] += scale*yi
1407                                         Vsum[j] += abs(scale)*v[j]
1408                            else:
1409                                Xminmax = [x[0],x[-1]]
1410                                YCsum = YBsum = YDsum = [0.0 for i in range(lenX)]
1411                                for j,yi in enumerate(y):
1412                                    Xsum.append(x[j])
1413                                    Ysum.append(scale*yi)
1414                                    Vsum.append(abs(scale*v[j]))
1415                    Wsum = 1./np.array(Vsum)
1416                    outname = 'PWDR '+result[-1]
1417                    Id = 0
1418                    if outname in Names:
1419                        dlg2 = wx.MessageDialog(self,'Overwrite data?','Duplicate data name',wx.OK|wx.CANCEL)
1420                        try:
1421                            if dlg2.ShowModal() == wx.ID_OK:
1422                                Id = G2gd.GetPatternTreeItemId(self,self.root,name)
1423                                self.PatternTree.Delete(Id)
1424                        finally:
1425                            dlg2.Destroy()
1426                    Id = self.PatternTree.AppendItem(parent=self.root,text=outname)
1427                    if Id:
1428                        Sample = G2pdG.SetDefaultSample()
1429                        self.PatternTree.SetItemPyData(Id,[{'wtFactor':1.0},[np.array(Xsum),np.array(Ysum),np.array(Wsum),
1430                            np.array(YCsum),np.array(YBsum),np.array(YDsum)]])
1431                        self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Comments'),Comments)                   
1432                        self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Limits'),[tuple(Xminmax),Xminmax])
1433                        self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Background'),[['chebyschev',True,3,1.0,0.0,0.0],
1434                            {'nDebye':0,'debyeTerms':[],'nPeaks':0,'peaksList':[]}])
1435                        self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Instrument Parameters'),Inst)
1436                        self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Sample Parameters'),Sample)
1437                        self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Peak List'),[])
1438                        self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Index Peak List'),[])
1439                        self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Unit Cells List'),[])             
1440                        self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Reflection Lists'),{})             
1441                        self.PatternTree.SelectItem(Id)
1442                        self.PatternTree.Expand(Id)
1443                   
1444            finally:
1445                dlg.Destroy()
1446
1447    def OnImageSum(self,event):
1448        TextList = []
1449        DataList = []
1450        SumList = []
1451        Names = []
1452        Inst = []
1453        SumItemList = []
1454        Comments = ['Sum equals: \n']
1455        if self.PatternTree.GetCount():
1456            item, cookie = self.PatternTree.GetFirstChild(self.root)
1457            while item:
1458                name = self.PatternTree.GetItemText(item)
1459                Names.append(name)
1460                if 'IMG' in name:
1461                    TextList.append([0.0,name])
1462                    DataList.append(self.PatternTree.GetItemPyData(item))        #Size,Image
1463                    Data = self.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(self,item,'Image Controls'))
1464                item, cookie = self.PatternTree.GetNextChild(self.root, cookie)
1465            if len(TextList) < 2:
1466                self.ErrorDialog('Not enough data to sum','There must be more than one "IMG" pattern')
1467                return
1468            TextList.append('default_sum_name')               
1469            dlg = self.SumDialog(self,'Sum data','Enter scale for each image in summation','IMG',TextList)
1470            try:
1471                if dlg.ShowModal() == wx.ID_OK:
1472                    imSize = 0
1473                    result = dlg.GetData()
1474                    First = True
1475                    Found = False
1476                    for i,item in enumerate(result[:-1]):
1477                        scale,name = item
1478                        data = DataList[i]
1479                        if scale:
1480                            Found = True                               
1481                            Comments.append("%10.3f %s" % (scale,' * '+name))
1482                            Npix,imagefile = data
1483                            image = G2IO.GetImageData(self,imagefile,imageOnly=True)
1484                            if First:
1485                                newImage = np.zeros_like(image)
1486                                First = False
1487                            if imSize:
1488                                if imSize != Npix:
1489                                    self.ErrorDialog('Image size error','Images to be summed must be same size'+ \
1490                                        '\nExpected:'+str(imSize)+ \
1491                                        '\nFound:   '+str(Npix)+'\nfor '+name)
1492                                    return
1493                                newImage = newImage+scale*image
1494                            else:
1495                                imSize = Npix
1496                                newImage = newImage+scale*image
1497                            del(image)
1498                    if not Found:
1499                        self.ErrorDialog('Image sum error','No nonzero image multipliers found')
1500                        return
1501                       
1502                    newImage = np.asfarray(newImage,dtype=np.float32)                       
1503                    outname = 'IMG '+result[-1]
1504                    Id = 0
1505                    if outname in Names:
1506                        dlg2 = wx.MessageDialog(self,'Overwrite data?','Duplicate data name',wx.OK|wx.CANCEL)
1507                        try:
1508                            if dlg2.ShowModal() == wx.ID_OK:
1509                                Id = G2gd.GetPatternTreeItemId(self,self.root,name)
1510                        finally:
1511                            dlg2.Destroy()
1512                    else:
1513                        Id = self.PatternTree.AppendItem(parent=self.root,text=outname)
1514                    if Id:
1515                        dlg = wx.FileDialog(self, 'Choose sum image filename', '.', '', 
1516                            'G2img files (*.G2img)|*.G2img', 
1517                            wx.SAVE|wx.FD_OVERWRITE_PROMPT|wx.CHANGE_DIR)
1518                        if dlg.ShowModal() == wx.ID_OK:
1519                            newimagefile = dlg.GetPath()
1520                            newimagefile = G2IO.FileDlgFixExt(dlg,newimagefile)
1521                            G2IO.PutG2Image(newimagefile,Comments,Data,Npix,newImage)
1522                            Imax = np.amax(newImage)
1523                            Imin = np.amin(newImage)
1524                            newImage = []
1525                            self.PatternTree.SetItemPyData(Id,[imSize,newimagefile])
1526                            self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Comments'),Comments)
1527                        del(newImage)
1528                        if self.imageDefault:
1529                            Data = copy.copy(self.imageDefault)
1530                        Data['showLines'] = True
1531                        Data['ring'] = []
1532                        Data['rings'] = []
1533                        Data['cutoff'] = 10
1534                        Data['pixLimit'] = 20
1535                        Data['ellipses'] = []
1536                        Data['calibrant'] = ''
1537                        Data['range'] = [(Imin,Imax),[Imin,Imax]]
1538                        self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Image Controls'),Data)                                           
1539                        Masks = {'Points':[],'Rings':[],'Arcs':[],'Polygons':[],'Thresholds':[(Imin,Imax),[Imin,Imax]]}
1540                        self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Masks'),Masks)
1541                        self.PatternTree.SelectItem(Id)
1542                        self.PatternTree.Expand(Id)
1543                        self.PickId = G2gd.GetPatternTreeItemId(self,self.root,outname)
1544                        self.Image = self.PickId
1545            finally:
1546                dlg.Destroy()
1547                     
1548    def OnAddPhase(self,event):
1549        if not G2gd.GetPatternTreeItemId(self,self.root,'Phases'):
1550            sub = self.PatternTree.AppendItem(parent=self.root,text='Phases')
1551        else:
1552            sub = G2gd.GetPatternTreeItemId(self,self.root,'Phases')
1553        PhaseName = ''
1554        dlg = wx.TextEntryDialog(None,'Enter a name for this phase','Phase Name Entry','New phase',
1555            style=wx.OK)
1556        if dlg.ShowModal() == wx.ID_OK:
1557            PhaseName = dlg.GetValue()
1558        dlg.Destroy()
1559        sub = self.PatternTree.AppendItem(parent=sub,text=PhaseName)
1560        E,SGData = G2spc.SpcGroup('P 1')
1561        self.PatternTree.SetItemPyData(sub,G2IO.SetNewPhase(Name=PhaseName,SGData=SGData))
1562       
1563    def OnDeletePhase(self,event):
1564        #Hmm, also need to delete this phase from Reflection Lists for each PWDR histogram
1565        if self.dataFrame:
1566            self.dataFrame.Clear() 
1567        TextList = []
1568        DelList = []
1569        DelItemList = []
1570        if G2gd.GetPatternTreeItemId(self,self.root,'Phases'):
1571            sub = G2gd.GetPatternTreeItemId(self,self.root,'Phases')
1572        else:
1573            return
1574        if sub:
1575            item, cookie = self.PatternTree.GetFirstChild(sub)
1576            while item:
1577                TextList.append(self.PatternTree.GetItemText(item))
1578                item, cookie = self.PatternTree.GetNextChild(sub, cookie)               
1579            dlg = wx.MultiChoiceDialog(self, 'Which phase to delete?', 'Delete phase', TextList, wx.CHOICEDLG_STYLE)
1580            try:
1581                if dlg.ShowModal() == wx.ID_OK:
1582                    result = dlg.GetSelections()
1583                    for i in result: DelList.append([i,TextList[i]])
1584                    item, cookie = self.PatternTree.GetFirstChild(sub)
1585                    i = 0
1586                    while item:
1587                        if [i,self.PatternTree.GetItemText(item)] in DelList: DelItemList.append(item)
1588                        item, cookie = self.PatternTree.GetNextChild(sub, cookie)
1589                        i += 1
1590                    for item in DelItemList:
1591                        name = self.PatternTree.GetItemText(item)
1592                        self.PatternTree.Delete(item)
1593                        self.G2plotNB.Delete(name)
1594                    item, cookie = self.PatternTree.GetFirstChild(self.root)
1595                    while item:
1596                        name = self.PatternTree.GetItemText(item)
1597                        if 'PWDR' in name:
1598                            Id = G2gd.GetPatternTreeItemId(self,item, 'Reflection Lists')
1599                            refList = self.PatternTree.GetItemPyData(Id)
1600                            for i,item in DelList:
1601                                del(refList[item])
1602                            self.PatternTree.SetItemPyData(Id,refList)
1603                        item, cookie = self.PatternTree.GetNextChild(self.root, cookie)
1604            finally:
1605                dlg.Destroy()
1606               
1607    def OnRenameData(self,event):
1608        name = self.PatternTree.GetItemText(self.PickId)     
1609        if 'PWDR' in name or 'HKLF' in name or 'IMG' in name:
1610            dataType = name[:name.index(' ')+1]                 #includes the ' '
1611            dlg = wx.TextEntryDialog(self,'Data name: '+dataType,'Change data name',
1612                defaultValue=name[name.index(' ')+1:])
1613            try:
1614                if dlg.ShowModal() == wx.ID_OK:
1615                    self.PatternTree.SetItemText(self.PickId,dataType+dlg.GetValue())
1616            finally:
1617                dlg.Destroy()
1618       
1619    def GetFileList(self,fileType,skip=None):        #potentially useful?
1620        fileList = []
1621        Source = ''
1622        id, cookie = self.PatternTree.GetFirstChild(self.root)
1623        while id:
1624            name = self.PatternTree.GetItemText(id)
1625            if fileType in name:
1626                if id == skip:
1627                    Source = name
1628                else:
1629                    fileList.append([False,name,id])
1630            id, cookie = self.PatternTree.GetNextChild(self.root, cookie)
1631        if skip:
1632            return fileList,Source
1633        else:
1634            return fileList
1635           
1636    def OnDataDelete(self, event):
1637        TextList = ['All Data']
1638        DelList = []
1639        DelItemList = []
1640        ifPWDR = False
1641        ifIMG = False
1642        ifHKLF = False
1643        ifPDF = False
1644        if self.PatternTree.GetCount():
1645            item, cookie = self.PatternTree.GetFirstChild(self.root)
1646            while item:
1647                name = self.PatternTree.GetItemText(item)
1648                if name not in ['Notebook','Controls','Covariance','Constraints','Restraints','Phases']:
1649                    if 'PWDR' in name: ifPWDR = True
1650                    if 'IMG' in name: ifIMG = True
1651                    if 'HKLF' in name: ifHKLF = True
1652                    if 'PDF' in name: ifPDF = True
1653                    TextList.append(name)
1654                item, cookie = self.PatternTree.GetNextChild(self.root, cookie)
1655            if ifPWDR: TextList.insert(1,'All PWDR')
1656            if ifIMG: TextList.insert(1,'All IMG')
1657            if ifHKLF: TextList.insert(1,'All HKLF')
1658            if ifPDF: TextList.insert(1,'All PDF')               
1659            dlg = wx.MultiChoiceDialog(self, 'Which data to delete?', 'Delete data', TextList, wx.CHOICEDLG_STYLE)
1660            try:
1661                if dlg.ShowModal() == wx.ID_OK:
1662                    result = dlg.GetSelections()
1663                    for i in result: DelList.append(TextList[i])
1664                    if 'All Data' in DelList:
1665                        DelList = [item for item in TextList if item[:3] != 'All']
1666                    elif 'All PWDR' in DelList:
1667                        DelList = [item for item in TextList if item[:4] == 'PWDR']
1668                    elif 'All IMG' in DelList:
1669                        DelList = [item for item in TextList if item[:3] == 'IMG']
1670                    elif 'All HKLF' in DelList:
1671                        DelList = [item for item in TextList if item[:4] == 'HKLF']
1672                    elif 'All PDF' in DelList:
1673                        DelList = [item for item in TextList if item[:3] == 'PDF']
1674                    item, cookie = self.PatternTree.GetFirstChild(self.root)
1675                    while item:
1676                        if self.PatternTree.GetItemText(item) in DelList: DelItemList.append(item)
1677                        item, cookie = self.PatternTree.GetNextChild(self.root, cookie)
1678                    for item in DelItemList:
1679                        self.PatternTree.Delete(item)
1680                    G2plt.PlotPatterns(self,True)                        #so plot gets updated
1681            finally:
1682                dlg.Destroy()
1683
1684    def OnFileOpen(self, event):
1685        result = ''
1686        Id = 0
1687        if self.PatternTree.GetChildrenCount(self.root,False):
1688            if self.dataFrame:
1689                self.dataFrame.Clear() 
1690            dlg = wx.MessageDialog(
1691                self,
1692                'Do you want to overwrite the current project? '
1693                'Any unsaved changes will be lost. Press OK to continue.',
1694                'Overwrite?',  wx.OK | wx.CANCEL)
1695            try:
1696                result = dlg.ShowModal()
1697                if result == wx.ID_OK:
1698                    self.PatternTree.DeleteChildren(self.root)
1699                    self.GSASprojectfile = ''
1700#                    self.PatternTree.DeleteChildren(self.root)
1701                    if self.HKL: self.HKL = []
1702                    if self.G2plotNB.plotList:
1703                        self.G2plotNB.clear()
1704            finally:
1705                dlg.Destroy()
1706        if result != wx.ID_CANCEL:   
1707            if self.dataDisplay: self.dataDisplay.Destroy()
1708            dlg = wx.FileDialog(self, 'Choose GSAS-II project file', '.', '', 
1709                'GSAS-II project file (*.gpx)|*.gpx',wx.OPEN|wx.CHANGE_DIR)
1710            try:
1711                if dlg.ShowModal() == wx.ID_OK:
1712                    self.GSASprojectfile = dlg.GetPath()
1713                    self.GSASprojectfile = G2IO.FileDlgFixExt(dlg,self.GSASprojectfile)
1714                    self.dirname = dlg.GetDirectory()
1715                    G2IO.ProjFileOpen(self)
1716                    self.PatternTree.SetItemText(self.root,'Loaded Data: '+self.GSASprojectfile)
1717                    self.PatternTree.Expand(self.root)
1718                    self.HKL = []
1719                    item, cookie = self.PatternTree.GetFirstChild(self.root)
1720                    while item and not Id:
1721                        name = self.PatternTree.GetItemText(item)
1722                        if name[:4] in ['PWDR','HKLF','IMG ','PDF ']:
1723                            Id = item
1724                        elif name == 'Controls':
1725                            data = self.PatternTree.GetItemPyData(item)
1726                            if data:
1727                                self.Refine.Enable(True)
1728                                self.SeqRefine.Enable(True)
1729                        item, cookie = self.PatternTree.GetNextChild(self.root, cookie)               
1730                    if Id:
1731                        self.PatternTree.SelectItem(Id)
1732                    self.CheckNotebook()
1733            finally:
1734                dlg.Destroy()
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 OnExportPatterns(self,event):
1789        names = ['All']
1790        exports = []
1791        item, cookie = self.PatternTree.GetFirstChild(self.root)
1792        while item:
1793            name = self.PatternTree.GetItemText(item)
1794            if 'PWDR' in name:
1795                names.append(name)
1796            item, cookie = self.PatternTree.GetNextChild(self.root, cookie)
1797        if names:
1798            dlg = wx.MultiChoiceDialog(self,'Select','Powder patterns to export',names)
1799            if dlg.ShowModal() == wx.ID_OK:
1800                sel = dlg.GetSelections()
1801                if sel[0] == 0:
1802                    exports = names[1:]
1803                else:
1804                    for x in sel:
1805                        exports.append(names[x])
1806            dlg.Destroy()
1807        if exports:
1808            dlg = wx.FileDialog(self, 'Choose output powder file name', '.', '', 
1809                'GSAS fxye file (*.fxye)|*.fxye|xye file (*.xye)|*.xye',
1810                wx.FD_SAVE|wx.FD_OVERWRITE_PROMPT|wx.CHANGE_DIR)
1811            try:
1812                if dlg.ShowModal() == wx.ID_OK:
1813                    powderfile = dlg.GetPath()
1814                    powderfile = G2IO.FileDlgFixExt(dlg,powderfile)
1815                    if 'fxye' in powderfile:
1816                        G2IO.powderFxyeSave(self,exports,powderfile)
1817                    else:       #just xye
1818                        G2IO.powderXyeSave(self,exports,powderfile)
1819            finally:
1820                dlg.Destroy()
1821       
1822    def OnExportPeakList(self,event):
1823        dlg = wx.FileDialog(self, 'Choose output peak list file name', '.', '', 
1824            '(*.*)|*.*',wx.FD_SAVE|wx.FD_OVERWRITE_PROMPT|wx.CHANGE_DIR)
1825        try:
1826            if dlg.ShowModal() == wx.ID_OK:
1827                self.peaklistfile = dlg.GetPath()
1828                self.peaklistfile = G2IO.FileDlgFixExt(dlg,self.peaklistfile)
1829                file = open(self.peaklistfile,'w')               
1830                item, cookie = self.PatternTree.GetFirstChild(self.root)
1831                while item:
1832                    name = self.PatternTree.GetItemText(item)
1833                    if 'PWDR' in name:
1834                        item2, cookie2 = self.PatternTree.GetFirstChild(item)
1835                        while item2:
1836                            name2 = self.PatternTree.GetItemText(item2)
1837                            if name2 == 'Peak List':
1838                                peaks = self.PatternTree.GetItemPyData(item2)
1839                                file.write("%s \n" % (name+' Peak List'))               
1840                                for peak in peaks:
1841                                    file.write("%10.4f %12.2f %10.3f %10.3f \n" % \
1842                                        (peak[0],peak[2],peak[4],peak[6]))
1843                            item2, cookie2 = self.PatternTree.GetNextChild(item, cookie2)                           
1844                    item, cookie = self.PatternTree.GetNextChild(self.root, cookie)                           
1845                file.close()
1846        finally:
1847            dlg.Destroy()
1848       
1849    def OnExportHKL(self,event):
1850        event.Skip()
1851       
1852    def OnExportPDF(self,event):
1853        #need S(Q) and G(R) to be saved here - probably best from selection?
1854        names = ['All']
1855        exports = []
1856        item, cookie = self.PatternTree.GetFirstChild(self.root)
1857        while item:
1858            name = self.PatternTree.GetItemText(item)
1859            if 'PDF' in name:
1860                names.append(name)
1861            item, cookie = self.PatternTree.GetNextChild(self.root, cookie)
1862        if names:
1863            dlg = wx.MultiChoiceDialog(self,'Select','PDF patterns to export',names)
1864            if dlg.ShowModal() == wx.ID_OK:
1865                sel = dlg.GetSelections()
1866                if sel[0] == 0:
1867                    exports = names[1:]
1868                else:
1869                    for x in sel:
1870                        exports.append(names[x])
1871            dlg.Destroy()
1872        if exports:
1873            G2IO.PDFSave(self,exports)
1874       
1875    def OnExportPhase(self,event):
1876        event.Skip()
1877       
1878    def OnExportCIF(self,event):
1879        event.Skip()
1880
1881    def OnMakePDFs(self,event):
1882        tth2q = lambda t,w:4.0*math.pi*sind(t/2.0)/w
1883        TextList = ['All PWDR']
1884        PDFlist = []
1885        Names = []
1886        if self.PatternTree.GetCount():
1887            id, cookie = self.PatternTree.GetFirstChild(self.root)
1888            while id:
1889                name = self.PatternTree.GetItemText(id)
1890                Names.append(name)
1891                if 'PWDR' in name:
1892                    TextList.append(name)
1893                id, cookie = self.PatternTree.GetNextChild(self.root, cookie)
1894            if len(TextList) == 1:
1895                self.ErrorDialog('Nothing to make PDFs for','There must be at least one "PWDR" pattern')
1896                return
1897            dlg = wx.MultiChoiceDialog(self,'Make PDF controls','Make PDF controls for:',TextList, wx.CHOICEDLG_STYLE)
1898            try:
1899                if dlg.ShowModal() == wx.ID_OK:
1900                    result = dlg.GetSelections()
1901                    for i in result: PDFlist.append(TextList[i])
1902                    if 0 in result:
1903                        PDFlist = [item for item in TextList if item[:4] == 'PWDR']                       
1904                    for item in PDFlist:
1905                        PWDRname = item[4:]
1906                        Id = self.PatternTree.AppendItem(parent=self.root,text='PDF '+PWDRname)
1907                        Data = {
1908                            'Sample':{'Name':item,'Mult':1.0,'Add':0.0},
1909                            'Sample Bkg.':{'Name':'','Mult':-1.0,'Add':0.0},
1910                            'Container':{'Name':'','Mult':-1.0,'Add':0.0},
1911                            'Container Bkg.':{'Name':'','Mult':-1.0,'Add':0.0},'ElList':{},
1912                            'Geometry':'Cylinder','Diam':1.0,'Pack':0.50,'Form Vol':10.0,
1913                            'DetType':'Image plate','ObliqCoeff':0.2,'Ruland':0.025,'QScaleLim':[0,100],
1914                            'Lorch':True,}
1915                        self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='PDF Controls'),Data)
1916                        self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='I(Q)'+PWDRname),[])       
1917                        self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='S(Q)'+PWDRname),[])       
1918                        self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='F(Q)'+PWDRname),[])       
1919                        self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='G(R)'+PWDRname),[])       
1920                self.ExportPDF.Enable(True)
1921            finally:
1922                dlg.Destroy()
1923               
1924    def GetPWDRdatafromTree(self,PWDRname):
1925        ''' Returns powder data from GSASII tree
1926        input:
1927            PWDRname = powder histogram name as obtained from GetHistogramNames
1928        return:
1929            PWDRdata = powder data dictionary with:
1930                Data - powder data arrays, Limits, Instrument Parameters, Sample Parameters           
1931        '''
1932        PWDRdata = {}
1933        PWDRdata['Data'] = self.PatternTree.GetItemPyData(PWDRname)[1]          #powder data arrays
1934        PWDRdata['Limits'] = self.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(self,PWDRname,'Limits'))
1935        PWDRdata['Background'] = self.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(self,PWDRname,'Background'))
1936        PWDRdata['Instrument Parameters'] = self.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(self,PWDRname,'Instrument Parameters'))
1937        PWDRdata['Sample Parameters'] = self.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(self,PWDRname,'Sample Parameters'))
1938        PWDRdata['Reflection Lists'] = self.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(self,PWDRname,'Reflection Lists'))
1939        return PWDRdata
1940
1941    def GetHKLFdatafromTree(self,HKLFname):
1942        ''' Returns single crystal data from GSASII tree
1943        input:
1944            HKLFname = single crystal histogram name as obtained from GetHistogramNames
1945        return:
1946            HKLFdata = single crystal data list of reflections: for each reflection:
1947                HKLF =
1948        '''
1949        HKLFdata = {}
1950        HKLFdata['Data'] = self.PatternTree.GetItemPyData(HKLFname)[1]
1951        HKLFdata['Instrument Parameters'] = self.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(self,HKLFname,'Instrument Parameters'))
1952        return HKLFdata
1953       
1954    def GetPhaseData(self):
1955        phaseData = {}
1956        if G2gd.GetPatternTreeItemId(self,self.root,'Phases'):
1957            sub = G2gd.GetPatternTreeItemId(self,self.root,'Phases')
1958        else:
1959            print 'no phases to be refined'
1960            return
1961        if sub:
1962            item, cookie = self.PatternTree.GetFirstChild(sub)
1963            while item:
1964                phaseData[self.PatternTree.GetItemText(item)] =  self.PatternTree.GetItemPyData(item)               
1965                item, cookie = self.PatternTree.GetNextChild(sub, cookie)
1966        return phaseData               
1967                   
1968    def GetUsedHistogramsAndPhasesfromTree(self):
1969        ''' Returns all histograms that are found in any phase
1970        and any phase that uses a histogram
1971        return:
1972            Histograms = dictionary of histograms as {name:data,...}
1973            Phases = dictionary of phases that use histograms
1974        '''
1975        phaseData = self.GetPhaseData()
1976        Histograms = {}
1977        Phases = {}
1978        pId = 0
1979        hId = 0
1980        for phase in phaseData:
1981            Phase = phaseData[phase]
1982            if Phase['Histograms']:
1983                if phase not in Phases:
1984                    Phase['pId'] = pId
1985                    pId += 1
1986                    Phases[phase] = Phase
1987                for hist in Phase['Histograms']:
1988                    if hist not in Histograms:
1989                        item = G2gd.GetPatternTreeItemId(self,self.root,hist)
1990                        if 'PWDR' in hist[:4]: 
1991                            Histograms[hist] = self.GetPWDRdatafromTree(item)
1992                        elif 'HKLF' in hist[:4]:
1993                            Histograms[hist] = self.GetHKLFdatafromTree(item)
1994                        #future restraint, etc. histograms here           
1995                        Histograms[hist]['hId'] = hId
1996                        hId += 1
1997        return Histograms,Phases
1998       
1999    class ViewParmDialog(wx.Dialog):
2000        def __init__(self,parent,title,parmDict):
2001            wx.Dialog.__init__(self,parent,-1,title,size=(300,430),
2002                pos=wx.DefaultPosition,style=wx.DEFAULT_DIALOG_STYLE)
2003            panel = wx.Panel(self,size=(300,430))
2004            parmNames = parmDict.keys()
2005            parmNames.sort()
2006            parmText = ' p:h:Parameter       refine?              value\n'
2007            for name in parmNames:
2008                parmData = parmDict[name]
2009                try:
2010                    parmText += ' %s \t%12.4g \n'%(name.ljust(19)+'\t'+parmData[1],parmData[0])
2011                except TypeError:
2012                    pass
2013            parmTable = wx.TextCtrl(panel,-1,parmText,
2014                style=wx.TE_MULTILINE|wx.TE_READONLY,size=(290,400))
2015            mainSizer = wx.BoxSizer(wx.VERTICAL)
2016            mainSizer.Add(parmTable)
2017            panel.SetSizer(mainSizer)
2018                           
2019    def OnViewLSParms(self,event):
2020        parmDict = {}
2021        Histograms,Phases = self.GetUsedHistogramsAndPhasesfromTree()
2022        print Histograms.keys()
2023        Natoms,atomIndx,phaseVary,phaseDict,pawleyLookup,FFtable,BLtable = G2str.GetPhaseData(Phases,RestDict=None,Print=False)       
2024        hapVary,hapDict,controlDict = G2str.GetHistogramPhaseData(Phases,Histograms,Print=False)
2025        histVary,histDict,controlDict = G2str.GetHistogramData(Histograms,Print=False)
2026        varyList = phaseVary+hapVary+histVary
2027        parmDict.update(phaseDict)
2028        parmDict.update(hapDict)
2029        parmDict.update(histDict)
2030        for parm in parmDict:
2031            if parm.split(':')[-1] in ['Azimuth','Gonio. radius','Lam1','Lam2',
2032                'Omega','Chi','Phi','nDebye','nPeaks']:
2033                parmDict[parm] = [parmDict[parm],' ']
2034            elif parm.split(':')[-2] in ['Ax','Ay','Az','SHmodel','SHord']:
2035                parmDict[parm] = [parmDict[parm],' ']
2036            elif parm in varyList:
2037                parmDict[parm] = [parmDict[parm],'True']
2038            else:
2039                parmDict[parm] = [parmDict[parm],'False']
2040        parmDict[' Num refined'] = [len(varyList),'']
2041        dlg = self.ViewParmDialog(self,'Parameters for least squares',parmDict)
2042        try:
2043            if dlg.ShowModal() == wx.ID_OK:
2044                print 'do something with changes?? - No!'
2045        finally:
2046            dlg.Destroy()
2047       
2048    def OnRefine(self,event):
2049        self.OnFileSave(event)
2050        # check that constraints are OK here
2051        errmsg, warnmsg = G2str.CheckConstraints(self.GSASprojectfile)
2052        if errmsg:
2053            print('Error in constraints:\n'+errmsg+
2054                  '\nRefinement not possible')
2055            self.ErrorDialog('Constraint Error',
2056                             'Error in constraints:\n'+errmsg+
2057                             '\nRefinement not possible')
2058            return
2059        if warnmsg:
2060            print('Conflict between refinment flag settings and constraints:\n'+
2061                  warnmsg+'\nRefinement not possible')
2062            self.ErrorDialog('Refinement Flag Error',
2063                             'Conflict between refinment flag settings and constraints:\n'+
2064                             warnmsg+
2065                             '\nRefinement not possible')
2066            return
2067        #works - but it'd be better if it could restore plots
2068        dlg = wx.ProgressDialog('Residual','All data Rw =',101.0, 
2069            style = wx.PD_ELAPSED_TIME|wx.PD_AUTO_HIDE|wx.PD_CAN_ABORT)
2070        screenSize = wx.ClientDisplayRect()
2071        Size = dlg.GetSize()
2072        Size = (int(Size[0]*1.2),Size[1]) # increase size a bit along x
2073        dlg.SetPosition(wx.Point(screenSize[2]-Size[0]-305,screenSize[1]+5))
2074        dlg.SetSize(Size)
2075        Rw = 100.00
2076        try:
2077            Rw = G2str.Refine(self.GSASprojectfile,dlg)
2078        finally:
2079            dlg.Destroy()       
2080        dlg = wx.MessageDialog(self,'Load new result?','Refinement results, Rw =%.3f'%(Rw),wx.OK|wx.CANCEL)
2081        try:
2082            if dlg.ShowModal() == wx.ID_OK:
2083                Id = 0
2084                self.PatternTree.DeleteChildren(self.root)
2085                if self.HKL: self.HKL = []
2086                if self.G2plotNB.plotList:
2087                    self.G2plotNB.clear()
2088                G2IO.ProjFileOpen(self)
2089                item, cookie = self.PatternTree.GetFirstChild(self.root)
2090                while item and not Id:
2091                    name = self.PatternTree.GetItemText(item)
2092                    if name[:4] in ['PWDR','HKLF']:
2093                        Id = item
2094                    item, cookie = self.PatternTree.GetNextChild(self.root, cookie)               
2095                if Id:
2096                    self.PatternTree.SelectItem(Id)
2097        finally:
2098            dlg.Destroy()
2099
2100    def OnSeqRefine(self,event):
2101        Id = G2gd.GetPatternTreeItemId(self,self.root,'Sequental results')
2102        if not Id:
2103            Id = self.PatternTree.AppendItem(self.root,text='Sequental results')
2104            self.PatternTree.SetItemPyData(Id,{})           
2105        self.OnFileSave(event)
2106        # check that constraints are OK here
2107        errmsg, warnmsg = G2str.CheckConstraints(self.GSASprojectfile)
2108        if errmsg:
2109            print('Error in constraints:\n'+errmsg+
2110                  '\nRefinement not possible')
2111            self.ErrorDialog('Constraint Error',
2112                             'Error in constraints:\n'+errmsg+
2113                             '\nRefinement not possible')
2114            return
2115        if warnmsg:
2116            print('Conflict between refinment flag settings and constraints:\n'+
2117                  warnmsg+'\nRefinement not possible')
2118            self.ErrorDialog('Refinement Flag Error',
2119                             'Conflict between refinment flag settings and constraints:\n'+
2120                             warnmsg+'\nRefinement not possible')
2121            return
2122        dlg = wx.ProgressDialog('Residual for histogram 0','Powder profile Rwp =',101.0, 
2123            style = wx.PD_ELAPSED_TIME|wx.PD_AUTO_HIDE|wx.PD_CAN_ABORT)
2124        screenSize = wx.ClientDisplayRect()
2125        Size = dlg.GetSize()
2126        Size = (int(Size[0]*1.2),Size[1]) # increase size a bit along x
2127        dlg.SetPosition(wx.Point(screenSize[2]-Size[0]-305,screenSize[1]+5))
2128        dlg.SetSize(Size)
2129        try:
2130            G2str.SeqRefine(self.GSASprojectfile,dlg)
2131        finally:
2132            dlg.Destroy()       
2133        dlg = wx.MessageDialog(self,'Load new result?','Refinement results',wx.OK|wx.CANCEL)
2134        try:
2135            if dlg.ShowModal() == wx.ID_OK:
2136                Id = 0
2137                self.PatternTree.DeleteChildren(self.root)
2138                if self.HKL: self.HKL = []
2139                if self.G2plotNB.plotList:
2140                    self.G2plotNB.clear()
2141                G2IO.ProjFileOpen(self)
2142                item, cookie = self.PatternTree.GetFirstChild(self.root)
2143                while item and not Id:
2144                    name = self.PatternTree.GetItemText(item)
2145                    if name[:4] in ['PWDR','HKLF']:
2146                        Id = item
2147                    item, cookie = self.PatternTree.GetNextChild(self.root, cookie)               
2148                if Id:
2149                    self.PatternTree.SelectItem(Id)
2150        finally:
2151            dlg.Destroy()
2152       
2153    def ErrorDialog(self,title,message,parent=None, wtype=wx.OK):
2154        result = None
2155        if parent is None:
2156            dlg = wx.MessageDialog(self, message, title,  wtype)
2157        else:
2158            dlg = wx.MessageDialog(parent, message, title,  wtype)
2159            dlg.CenterOnParent() # not working on Mac
2160        try:
2161            result = dlg.ShowModal()
2162        finally:
2163            dlg.Destroy()
2164        return result
2165
2166class GSASIImain(wx.App):
2167    def OnInit(self):
2168        self.main = GSASII(None)
2169        self.main.Show()
2170        self.SetTopWindow(self.main)
2171        return True
2172
2173def main():
2174    application = GSASIImain(0)
2175    if wxInspector: wxeye.InspectionTool().Show()
2176
2177    #application.main.OnRefine(None)
2178    application.MainLoop()
2179   
2180if __name__ == '__main__':
2181    main()
Note: See TracBrowser for help on using the repository browser.