source: trunk/GSASII.py @ 762

Last change on this file since 762 was 762, checked in by toby, 10 years ago

update py files to use native line ends, add update from svn to help menu when svn or svn.exe is in path or ./svn/bin

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