source: trunk/GSASII.py @ 709

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

add testGSASIIstruct.py
a fix to the data window restore after Refine
make getMass & getDensity routines in GSASIImath.py
update atom mass info after Refine

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