source: trunk/GSASII.py @ 564

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

change opengl install to work locally if needed

  • Property svn:keywords set to Date Author Revision URL Id
File size: 82.6 KB
Line 
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3#GSASII
4########### SVN repository information ###################
5# $Date: 2012-04-20 16:54:15 +0000 (Fri, 20 Apr 2012) $
6# $Author: toby $
7# $Revision: 564 $
8# $URL: trunk/GSASII.py $
9# $Id: GSASII.py 564 2012-04-20 16:54:15Z toby $
10########### SVN repository information ###################
11
12import os
13import os.path as ospath
14import sys
15import math
16#import cPickle
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',ospath.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',ospath.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
59import GSASIIIO as G2IO
60import GSASIIgrid as G2gd
61import GSASIIplot as G2plt
62import GSASIIpwdGUI as G2pdG
63import GSASIIspc as G2spc
64import GSASIIstruct as G2str
65import GSASIImapvars as G2mv
66import GSASIIsolve as G2sol
67
68#wx inspector - use as needed
69wxInspector = False
70
71# print versions
72print "Available python module versions for GSASII:"
73print "python:     ",sys.version[:5]
74print "wxpython:   ",wx.__version__
75print "matplotlib: ",mpl.__version__
76print "numpy:      ",np.__version__
77print "scipy:      ",sp.__version__
78print "OpenGL:     ",ogl.__version__
79try:
80    import mkl
81    print "Max threads ",mkl.get_max_threads()
82except:
83    print "MKL module not present"
84__version__ = '0.1.5'
85G2gd.__version__ = __version__
86print "This is GSAS-II version:     ",__version__
87
88# useful degree trig functions
89sind = lambda x: math.sin(x*math.pi/180.)
90cosd = lambda x: math.cos(x*math.pi/180.)
91tand = lambda x: math.tan(x*math.pi/180.)
92asind = lambda x: 180.*math.asin(x)/math.pi
93acosd = lambda x: 180.*math.acos(x)/math.pi
94atan2d = lambda x,y: 180.*math.atan2(y,x)/math.pi
95
96def create(parent):
97    return GSASII(parent)
98
99[wxID_PATTERNTREE, 
100] = [wx.NewId() for _init_ctrls in range(1)]
101
102[wxID_FILECLOSE, wxID_FILEEXIT, wxID_FILEOPEN,  wxID_FILESAVE, wxID_FILESAVEAS, 
103wxID_REFINE,  wxID_MAKEPDFS, wxID_VIEWLSPARMS, wxID_SEQREFINE,
104] = [wx.NewId() for _init_coll_File_Items in range(9)]
105
106[wxID_PWDRREAD,wxID_SNGLREAD,wxID_ADDPHASE,wxID_DELETEPHASE,
107 wxID_DATADELETE,wxID_READPEAKS,wxID_PWDSUM,wxID_IMGREAD,
108 wxID_IMSUM, wxID_DATARENAME,
109] = [wx.NewId() for _init_coll_Data_Items in range(10)]
110
111[wxID_IMPORT, wxID_IMPORTPATTERN, wxID_IMPORTHKL
112#, wxID_IMPORTPHASE,
113#wxID_IMPORTCIF, wxID_IMPORTPDB, 
114] = [wx.NewId() for _init_coll_Import_Items in range(3)]
115
116[wxID_EXPORT, wxID_EXPORTPATTERN, wxID_EXPORTHKL, wxID_EXPORTPHASE,
117wxID_EXPORTCIF, wxID_EXPORTPEAKLIST, wxID_EXPORTPDF,
118] = [wx.NewId() for _init_coll_Export_Items in range(7)]
119
120class GSASII(wx.Frame):
121   
122    def _init_coll_GSASIIMenu_Menus(self, parent):
123        parent.Append(menu=self.File, title='File')
124        parent.Append(menu=self.Data, title='Data')
125        parent.Append(menu=self.Calculate, title='Calculate')
126        parent.Append(menu=self.Import, title='Import')
127        parent.Append(menu=self.Export, title='Export')
128        parent.Append(menu=G2gd.MyHelp(self,helpType='Data tree'),title='&Help' )
129
130    def _init_coll_File_Items(self, parent):
131        parent.Append(help='Open a gsasii project file (*.gpx)', id=wxID_FILEOPEN,
132             kind=wx.ITEM_NORMAL,text='Open project...')
133        parent.Append(help='Save project to old file', id=wxID_FILESAVE, 
134            kind=wx.ITEM_NORMAL,text='Save project')
135        parent.Append(help='Save project to new file', id=wxID_FILESAVEAS, 
136            kind=wx.ITEM_NORMAL,text='Save As...')
137        parent.Append(help='Close project, saving is optional', id=wxID_FILECLOSE, 
138            kind=wx.ITEM_NORMAL,text='Close project')
139        parent.Append(help='Exit from gsasii', id=wxID_FILEEXIT, kind=wx.ITEM_NORMAL,
140            text='Exit')
141        self.Bind(wx.EVT_MENU, self.OnFileOpen, id=wxID_FILEOPEN)
142        self.Bind(wx.EVT_MENU, self.OnFileSave, id=wxID_FILESAVE)
143        self.Bind(wx.EVT_MENU, self.OnFileSaveas, id=wxID_FILESAVEAS)
144        self.Bind(wx.EVT_MENU, self.OnFileClose, id=wxID_FILECLOSE)
145        self.Bind(wx.EVT_MENU, self.OnFileExit, id=wxID_FILEEXIT)
146       
147    def _init_coll_Data_Items(self,parent):
148        parent.Append(help='', id=wxID_PWDRREAD, kind=wx.ITEM_NORMAL,
149            text='Read powder data...')
150        parent.Append(help='',id=wxID_IMGREAD, kind=wx.ITEM_NORMAL,
151            text='Read image data...')
152        parent.Append(help='',id=wxID_READPEAKS, kind=wx.ITEM_NORMAL,
153            text='Read Powder Pattern Peaks...')
154        parent.Append(help='', id=wxID_SNGLREAD, kind=wx.ITEM_NORMAL,
155            text='Read single crystal data...')
156        parent.Append(help='', id=wxID_PWDSUM, kind=wx.ITEM_NORMAL,
157            text='Sum powder data')
158        parent.Append(help='',id=wxID_IMSUM, kind=wx.ITEM_NORMAL,
159            text='Sum image data')
160        parent.Append(help='', id=wxID_ADDPHASE, kind=wx.ITEM_NORMAL,
161            text='Add phase')
162        parent.Append(help='', id=wxID_DELETEPHASE, kind=wx.ITEM_NORMAL,
163            text='Delete phase')
164        parent.Append(help='', id=wxID_DATARENAME, kind=wx.ITEM_NORMAL,
165            text='Rename data') 
166        parent.Append(help='', id=wxID_DATADELETE, kind=wx.ITEM_NORMAL,
167            text='Delete data')
168        self.Bind(wx.EVT_MENU, self.OnPwdrRead, id=wxID_PWDRREAD)
169        self.Bind(wx.EVT_MENU, self.OnPwdrSum, id=wxID_PWDSUM)
170        self.Bind(wx.EVT_MENU, self.OnReadPowderPeaks, id=wxID_READPEAKS)
171        self.Bind(wx.EVT_MENU, self.OnImageRead, id=wxID_IMGREAD)
172        self.Bind(wx.EVT_MENU, self.OnImageSum, id=wxID_IMSUM)
173        self.Bind(wx.EVT_MENU, self.OnSnglRead, id=wxID_SNGLREAD)
174        self.Bind(wx.EVT_MENU, self.OnAddPhase, id=wxID_ADDPHASE)
175        self.Bind(wx.EVT_MENU, self.OnDeletePhase, id=wxID_DELETEPHASE)
176        self.Bind(wx.EVT_MENU, self.OnRenameData, id=wxID_DATARENAME)
177        self.Bind(wx.EVT_MENU, self.OnDataDelete, id=wxID_DATADELETE)
178               
179    def _init_coll_Calculate_Items(self,parent):
180        self.MakePDF = parent.Append(help='Make new PDFs from selected powder patterns', 
181            id=wxID_MAKEPDFS, kind=wx.ITEM_NORMAL,text='Make new PDFs')
182        self.Bind(wx.EVT_MENU, self.OnMakePDFs, id=wxID_MAKEPDFS)
183        self.ViewLSParms = parent.Append(help='View least squares parameters', 
184            id=wxID_VIEWLSPARMS, kind=wx.ITEM_NORMAL,text='View LS parms')
185        self.Bind(wx.EVT_MENU, self.OnViewLSParms, id=wxID_VIEWLSPARMS)
186        self.Refine = parent.Append(help='', id=wxID_REFINE, kind=wx.ITEM_NORMAL,
187            text='Refine')
188        self.Refine.Enable(False)
189        self.Bind(wx.EVT_MENU, self.OnRefine, id=wxID_REFINE)
190        self.SeqRefine = parent.Append(help='', id=wxID_SEQREFINE, kind=wx.ITEM_NORMAL,
191            text='Sequental refine')
192        self.SeqRefine.Enable(False)
193        self.Bind(wx.EVT_MENU, self.OnSeqRefine, id=wxID_SEQREFINE)
194       
195    def _init_Import_Phase(self,parent):
196        '''import all the G2importphase*.py files that are found in the
197        path and configure the Import Phase menus accordingly
198        '''
199
200        path2GSAS2 = os.path.dirname(os.path.realpath(__file__)) # location of this file
201        pathlist = sys.path[:]
202        if path2GSAS2 not in pathlist: pathlist.append(path2GSAS2)
203        filelist = []
204        for path in pathlist:
205            for filename in glob.iglob(os.path.join(path, "G2importphase*.py")):
206                filelist.append(filename)   
207                #print 'found',filename
208        filelist = sorted(list(set(filelist))) # remove duplicates
209        self.ImportPhaseReaderlist = []
210        for filename in filelist:
211            path,rootname = os.path.split(filename)
212            pkg = os.path.splitext(rootname)[0]
213            try:
214                fp = None
215                fp, fppath,desc = imp.find_module(pkg,[path,])
216                pkg = imp.load_module(pkg,fp,fppath,desc)
217                for clss in inspect.getmembers(pkg): # find classes defined in package
218                    if clss[0].startswith('_'): continue
219                    if inspect.isclass(clss[1]):
220                        # check if we have the required methods
221                        for m in 'Reader','ExtensionValidator','ContentsValidator':
222                            if not hasattr(clss[1],m): break
223                            if not callable(getattr(clss[1],m)): break
224                        else:
225                            reader = clss[1]() # create a phase import instance
226                            self.ImportPhaseReaderlist.append(reader)
227            except AttributeError:
228                print 'Import_Phase: Attribute Error',filename
229                pass
230            except ImportError:
231                print 'Import_Phase: Error importing file',filename
232                pass
233            finally:
234                if fp: fp.close()
235        submenu = wx.Menu()
236        item = parent.AppendMenu(wx.ID_ANY, 'Import Phase menu',
237            submenu, help='Import phase data')
238        self.PhaseImportMenuId = {}
239        item = submenu.Append(wx.ID_ANY,
240                              help='Import phase data based selected by extension',
241                              kind=wx.ITEM_NORMAL,text='Import Phase by extension')
242        self.Bind(wx.EVT_MENU, self.OnImportPhaseGeneric, id=item.GetId())
243        for reader in self.ImportPhaseReaderlist:
244            item = submenu.Append(wx.ID_ANY,
245                help='Import specific format phase data',
246                kind=wx.ITEM_NORMAL,text='Import Phase '+reader.formatName+'...')
247            self.PhaseImportMenuId[item.GetId()] = reader
248            self.Bind(wx.EVT_MENU, self.OnImportPhaseGeneric, id=item.GetId())
249
250    def OnImportPhaseGeneric(self,event):
251        # find out which format was requested
252        reader = self.PhaseImportMenuId.get(event.GetId())
253        if reader is None:
254            #print "use all formats"
255            readerlist = self.ImportPhaseReaderlist
256            choices = "any file (*.*)|*.*"
257            extdict = {}
258            # compile a list of allowed extensions
259            for rd in readerlist:
260                fmt = rd.formatName
261                for extn in rd.extensionlist:
262                    if not extdict.get(extn): extdict[extn] = []
263                    extdict[extn] += [fmt,]
264            for extn in sorted(extdict.keys(),cmp=lambda x,y: cmp(x.lower(), y.lower())):
265                fmt = ''
266                for f in extdict[extn]:
267                    if fmt != "": fmt += ', '
268                    fmt += f
269                choices += "|" + fmt + " file (*" + extn + ")|*" + extn
270        else:
271            readerlist = [reader,]
272            # compile a list of allowed extensions
273            choices = reader.formatName + " file ("
274            w = ""
275            for extn in reader.extensionlist:
276                if w != "": w += ";"
277                w += "*" + extn
278            choices += w + ")|" + w
279            if not reader.strictExtension:
280                choices += "|any file (*.*)|*.*"
281        # get the file
282        dlg = wx.FileDialog(
283            self, message="Choose phase input file",
284            #defaultDir=os.getcwd(),
285            defaultFile="",
286            wildcard=choices,
287            style=wx.OPEN | wx.CHANGE_DIR
288            )
289        try:
290            if dlg.ShowModal() == wx.ID_OK:
291                file = dlg.GetPath()
292            else: # cancel was pressed
293                return
294        finally:
295            dlg.Destroy()
296        # set what formats are compatible with this file
297        primaryReaders = []
298        secondaryReaders = []
299        for reader in readerlist:
300            flag = reader.ExtensionValidator(file)
301            if flag is None: 
302                secondaryReaders.append(reader)
303            elif flag:
304                primaryReaders.append(reader)
305        if len(secondaryReaders) + len(primaryReaders) == 0:
306            self.ErrorDialog('No matching format for file '+file,'No Format')
307            return
308       
309        fp = None
310        try:
311            fp = open(file,'r')
312            # try the file first with Readers that specify the
313            # files extension and later with ones that allow it
314            for rd in primaryReaders+secondaryReaders:
315                if not rd.ContentsValidator(fp):
316                    continue # rejected on cursory check
317                #flag = rd.Reader(file,fp,self)
318                try:
319                    flag = rd.Reader(file,fp,self)
320                except:
321                    import traceback
322                    print traceback.format_exc()
323                    self.ErrorDialog('Error reading file '+file
324                        +' with format '+ rd.formatName,'Read Error')
325                    continue
326                if not flag: continue
327                dlg = wx.TextEntryDialog( # allow editing of phase name
328                    self, 'Enter the name for the new phase',
329                    'Edit phase name', rd.Phase['General']['Name'],
330                    style=wx.OK)
331                #dlg.SetValue("Python is the best!")
332                dlg.CenterOnParent()
333                if dlg.ShowModal() == wx.ID_OK:
334                    rd.Phase['General']['Name'] = dlg.GetValue()
335                dlg.Destroy()
336                PhaseName = rd.Phase['General']['Name']
337                if not G2gd.GetPatternTreeItemId(self,self.root,'Phases'):
338                    sub = self.PatternTree.AppendItem(parent=self.root,text='Phases')
339                else:
340                    sub = G2gd.GetPatternTreeItemId(self,self.root,'Phases')
341                psub = self.PatternTree.AppendItem(parent=sub,text=PhaseName)
342                self.PatternTree.SetItemPyData(psub,rd.Phase)
343                self.PatternTree.Expand(self.root) # make sure phases are seen
344                self.PatternTree.Expand(sub) 
345                self.PatternTree.Expand(psub) 
346                return # success
347        except:
348            import traceback
349            print traceback.format_exc()
350            self.ErrorDialog('Error on open of file '+file,'Open Error')
351        finally:
352            if fp: fp.close()
353
354        return
355       
356
357    def _init_coll_Import_Items(self,parent):
358        self.ImportPattern = parent.Append(help='',id=wxID_IMPORTPATTERN, kind=wx.ITEM_NORMAL,
359            text='Import Powder Pattern...')
360        self.ImportHKL = parent.Append(help='',id=wxID_IMPORTHKL, kind=wx.ITEM_NORMAL,
361            text='Import HKLs...')
362        self.Bind(wx.EVT_MENU, self.OnImportPattern, id=wxID_IMPORTPATTERN)
363        self.Bind(wx.EVT_MENU, self.OnImportHKL, id=wxID_IMPORTHKL)
364
365    def _init_coll_Export_Items(self,parent):
366        self.ExportPattern = parent.Append(help='Select PWDR item to enable',id=wxID_EXPORTPATTERN, kind=wx.ITEM_NORMAL,
367            text='Export Powder Patterns...')
368        self.ExportPeakList = parent.Append(help='',id=wxID_EXPORTPEAKLIST, kind=wx.ITEM_NORMAL,
369            text='Export All Peak Lists...')
370        self.ExportHKL = parent.Append(help='',id=wxID_EXPORTHKL, kind=wx.ITEM_NORMAL,
371            text='Export HKLs...')
372        self.ExportPDF = parent.Append(help='Select PDF item to enable',id=wxID_EXPORTPDF, kind=wx.ITEM_NORMAL,
373            text='Export PDF...')
374        self.ExportPhase = parent.Append(help='',id=wxID_EXPORTPHASE, kind=wx.ITEM_NORMAL,
375            text='Export Phase...')
376        self.ExportCIF = parent.Append(help='',id=wxID_EXPORTCIF, kind=wx.ITEM_NORMAL,
377            text='Export CIF...')
378        self.ExportPattern.Enable(False)
379        self.ExportPeakList.Enable(True)
380        self.ExportHKL.Enable(False)
381        self.ExportPDF.Enable(False)
382        self.ExportPhase.Enable(False)
383        self.ExportCIF.Enable(False)
384        self.Bind(wx.EVT_MENU, self.OnExportPatterns, id=wxID_EXPORTPATTERN)
385        self.Bind(wx.EVT_MENU, self.OnExportPeakList, id=wxID_EXPORTPEAKLIST)
386        self.Bind(wx.EVT_MENU, self.OnExportHKL, id=wxID_EXPORTHKL)
387        self.Bind(wx.EVT_MENU, self.OnExportPDF, id=wxID_EXPORTPDF)
388        self.Bind(wx.EVT_MENU, self.OnExportPhase, id=wxID_EXPORTPHASE)
389        self.Bind(wx.EVT_MENU, self.OnExportCIF, id=wxID_EXPORTCIF)
390               
391    def _init_utils(self):
392        self.GSASIIMenu = wx.MenuBar()
393        self.File = wx.Menu(title='')
394        self.Data = wx.Menu(title='')       
395        self.Calculate = wx.Menu(title='')       
396        self.Import = wx.Menu(title='')       
397        self.Export = wx.Menu(title='')       
398
399        self._init_coll_GSASIIMenu_Menus(self.GSASIIMenu)
400        self._init_coll_File_Items(self.File)
401        self._init_coll_Data_Items(self.Data)
402        self._init_coll_Calculate_Items(self.Calculate)
403        self._init_Import_Phase(self.Import)
404        self._init_coll_Import_Items(self.Import)
405        self._init_coll_Export_Items(self.Export)
406       
407    def _init_ctrls(self, parent):
408        wx.Frame.__init__(self, name='GSASII', parent=parent,
409            size=wx.Size(300, 250),style=wx.DEFAULT_FRAME_STYLE, title='GSAS-II data tree')
410        clientSize = wx.ClientDisplayRect()
411        Size = self.GetSize()
412        xPos = clientSize[2]-Size[0]
413        self.SetPosition(wx.Point(xPos,clientSize[1]))
414        self._init_utils()
415        self.SetMenuBar(self.GSASIIMenu)
416        self.Bind(wx.EVT_SIZE, self.OnSize)
417        self.CreateStatusBar()
418        self.mainPanel = wx.Panel(self,-1)
419       
420        self.PatternTree = wx.TreeCtrl(id=wxID_PATTERNTREE,
421            parent=self.mainPanel, pos=wx.Point(0, 0),style=wx.TR_DEFAULT_STYLE )
422        self.PatternTree.Bind(wx.EVT_TREE_SEL_CHANGED,
423            self.OnPatternTreeSelChanged, id=wxID_PATTERNTREE)
424        self.PatternTree.Bind(wx.EVT_TREE_ITEM_COLLAPSED,
425            self.OnPatternTreeItemCollapsed, id=wxID_PATTERNTREE)
426        self.PatternTree.Bind(wx.EVT_TREE_ITEM_EXPANDED,
427            self.OnPatternTreeItemExpanded, id=wxID_PATTERNTREE)
428        self.PatternTree.Bind(wx.EVT_TREE_DELETE_ITEM,
429            self.OnPatternTreeItemDelete, id=wxID_PATTERNTREE)
430        self.PatternTree.Bind(wx.EVT_TREE_KEY_DOWN,
431            self.OnPatternTreeKeyDown, id=wxID_PATTERNTREE)
432        self.root = self.PatternTree.AddRoot('Loaded Data: ')
433       
434        plotFrame = wx.Frame(None,-1,'GSASII Plots',size=wx.Size(700,600), \
435            style=wx.DEFAULT_FRAME_STYLE ^ wx.CLOSE_BOX)
436        self.G2plotNB = G2plt.G2PlotNoteBook(plotFrame)
437        plotFrame.Show()
438       
439        self.dataDisplay = None
440       
441    def __init__(self, parent):
442        self._init_ctrls(parent)
443        self.Bind(wx.EVT_CLOSE, self.ExitMain)
444        # various defaults
445        self.oldFocus = None
446        self.GSASprojectfile = ''
447        self.dirname = ospath.expanduser('~')       #start in the users home directory by default; may be meaningless
448        self.undofile = ''
449        self.TreeItemDelete = False
450        self.Offset = [0.0,0.0]
451        self.delOffset = .02
452        self.refOffset = -100.0
453        self.refDelt = .01
454        self.Weight = False
455        self.IparmName = ''
456        self.IfPlot = False
457        self.PatternId = 0
458        self.PickId = 0
459        self.PeakTable = []
460        self.LimitsTable = []
461        self.HKL = []
462        self.Lines = []
463        self.itemPicked = None
464        self.dataFrame = None
465        self.Interpolate = 'nearest'
466        self.ContourColor = 'Paired'
467        self.VcovColor = 'RdYlGn'
468        self.Projection = 'equal area'
469        self.logPlot = False
470        self.qPlot = False
471        self.Contour = False
472        self.Legend = False
473        self.SinglePlot = False
474        self.plotView = 0
475        self.Image = 0
476        self.oldImagefile = ''
477        self.ImageZ = []
478        self.Integrate = 0
479        self.Pwdr = False
480        self.imageDefault = {}
481        self.Sngl = 0
482        self.ifGetRing = False
483        self.setPoly = False
484        arg = sys.argv
485        if len(arg) > 1:
486            self.GSASprojectfile = arg[1]
487            self.dirname = ospath.dirname(arg[1])
488            if self.dirname: os.chdir(self.dirname)
489            G2IO.ProjFileOpen(self)
490            self.PatternTree.Expand(self.root)
491            self.Refine.Enable(True)
492            self.SeqRefine.Enable(True)
493            #self.Solve.Enable(True) # what is this? (BHT)
494
495    def OnSize(self,event):
496        w,h = self.GetClientSizeTuple()
497        self.mainPanel.SetSize(wx.Size(w,h))
498        self.PatternTree.SetSize(wx.Size(w,h))
499                       
500    def OnPatternTreeSelChanged(self, event):
501        if self.TreeItemDelete:
502            self.TreeItemDelete = False
503        else:
504            pltNum = self.G2plotNB.nb.GetSelection()
505            if pltNum >= 0:                         #to avoid the startup with no plot!
506                pltPage = self.G2plotNB.nb.GetPage(pltNum)
507                pltPlot = pltPage.figure
508            item = event.GetItem()
509            G2gd.MovePatternTreeToGrid(self,item)
510            if self.oldFocus:
511                self.oldFocus.SetFocus()
512       
513    def OnPatternTreeItemCollapsed(self, event):
514        event.Skip()
515
516    def OnPatternTreeItemExpanded(self, event):
517        event.Skip()
518       
519    def OnPatternTreeItemDelete(self, event):
520        self.TreeItemDelete = True
521
522    def OnPatternTreeItemActivated(self, event):
523        event.Skip()
524       
525    def OnPatternTreeKeyDown(self,event):
526        key = event.GetKeyCode()
527        item = self.PickId
528        if type(item) is int: return # is this the toplevel in tree?
529        if key == wx.WXK_UP:
530            self.oldFocus = wx.Window.FindFocus()
531            self.PatternTree.GetPrevSibling(item)
532        elif key == wx.WXK_DOWN:
533            self.oldFocus = wx.Window.FindFocus()
534            self.PatternTree.GetNextSibling(item)
535               
536    def OnPwdrRead(self, event):
537        self.CheckNotebook()
538        dlg = wx.FileDialog(self, 'Choose files', '.', '', 
539            'GSAS fxye files (*.fxye)|*.fxye|GSAS fxy files (*.fxy)|*.fxy|Topas xye files (*.xye)|*.xye|All files (*.*)|*.*', 
540            wx.OPEN | wx.MULTIPLE | wx.CHANGE_DIR)
541        try:
542            if dlg.ShowModal() == wx.ID_OK:
543                filenames = dlg.GetPaths()
544                filenames.sort()
545                for filename in filenames:
546                    Data,Iparm,Comments,Temperature = G2IO.SelectPowderData(self, filename)              #Data: list of tuples (filename,Pos,Bank)
547                    if not Data:                                                    #if Data rejected by user - go to next one
548                        continue
549                    DataType = Iparm['INS   HTYPE ']                                #expect only 4 char string
550                    DataType = DataType.strip()[0:3]                                #just 1st 3 chars
551                    wx.BeginBusyCursor()
552                    Sample = G2pdG.SetDefaultSample()
553                    Sample['Temperature'] = Temperature
554                    try:
555                        for Item in Data:
556                            vals = Item[2].split()          #split up the BANK record
557                            Id = self.PatternTree.AppendItem(parent=self.root,text='PWDR '+ospath.basename(Item[0])+': '+vals[0]+vals[1])
558                            data = G2IO.GetPowderData(filename,Item[1],Item[2],DataType)
559                            self.PatternTree.SetItemPyData(Id,[Item,data])
560                            '''
561                            Each tree item data is a list with:
562                            Item: the (filename,Pos,Bank) tuple
563                            data: (x,y,w,yc,yb,yd) list  of np.arrays from GetPowderData
564                            '''
565                           
566                            self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Comments'),Comments)                           
567                            Tmin = min(data[0])
568                            Tmax = max(data[0])
569                            self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Limits'),[(Tmin,Tmax),[Tmin,Tmax]])
570                            self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Background'),[['chebyschev',True,3,1.0,0.0,0.0],
571                                {'nDebye':0,'debyeTerms':[],'nPeaks':0,'peaksList':[]}])
572       
573                            data = [DataType,]
574                            if 'C' in DataType:
575                                s = Iparm['INS  1 ICONS']
576                                v = (G2IO.sfloat(s[:10]),G2IO.sfloat(s[10:20]),G2IO.sfloat(s[20:30]),G2IO.sfloat(s[55:65]),G2IO.sfloat(s[40:50])) #get lam1, lam2, zero, pola & ratio
577                                if not v[1]:
578                                    names = ['Type','Lam','Zero','Polariz.','U','V','W','X','Y','SH/L','Azimuth'] 
579                                    v = (v[0],v[2],v[4])
580                                    codes = [0,0,0,0]
581                                else:
582                                    names = ['Type','Lam1','Lam2','Zero','I(L2)/I(L1)','Polariz.','U','V','W','X','Y','SH/L','Azimuth']
583                                    codes = [0,0,0,0,0,0]
584                                data.extend(v)
585                                v1 = Iparm['INS  1PRCF1 '].split()                                                 
586                                v = Iparm['INS  1PRCF11'].split()
587                                data.extend([float(v[0]),float(v[1]),float(v[2])])                  #get GU, GV & GW - always here
588                                try:
589                                    azm = float(Iparm['INS  1DETAZM'])
590                                except KeyError:                                                #not in this Iparm file
591                                    azm = 0.0
592                                v = Iparm['INS  1PRCF12'].split()
593                                if v1[0] == 3:
594                                    data.extend([float(v[0]),float(v[1]),float(v[2])+float(v[3],azm)])  #get LX, LY, S+H/L & azimuth
595                                else:
596                                    data.extend([0.0,0.0,0.002,azm])                                      #OK defaults if fxn #3 not 1st in iprm file
597                                codes.extend([0,0,0,0,0,0,0])
598                            self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Instrument Parameters'),[tuple(data),data,codes,names])
599                            self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Sample Parameters'),Sample)
600                            self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Peak List'),[])
601                            self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Index Peak List'),[])
602                            self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Unit Cells List'),[])
603                            self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Reflection Lists'),{})             
604                            self.PatternId = G2gd.GetPatternTreeItemId(self,Id,'Limits')
605                    finally:
606                        wx.EndBusyCursor()
607                self.PatternTree.Expand(Id)
608                self.PatternTree.SelectItem(Id)
609   
610        finally:
611            dlg.Destroy()
612       
613    def OnReadPowderPeaks(self,event):
614        Cuka = 1.54052
615        self.CheckNotebook()
616        dlg = wx.FileDialog(self, 'Choose file with peak list', '.', '', 
617            'peak files (*.txt)|*.txt|All files (*.*)|*.*',wx.OPEN|wx.CHANGE_DIR)
618        try:
619            if dlg.ShowModal() == wx.ID_OK:
620                self.HKL = []
621                self.powderfile = dlg.GetPath()
622                comments,peaks = G2IO.GetPowderPeaks(self.powderfile)
623                Id = self.PatternTree.AppendItem(parent=self.root,text='PKS '+ospath.basename(self.powderfile))
624                data = ['PKS',Cuka,0.0]
625                names = ['Type','Lam','Zero'] 
626                codes = [0,0]
627                self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Instrument Parameters'),[tuple(data),data,codes,names])
628                self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Comments'),comments)
629                self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Index Peak List'),peaks)
630                self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Unit Cells List'),[])             
631                self.PatternTree.Expand(Id)
632                self.PatternTree.SelectItem(Id)
633        finally:
634            dlg.Destroy()
635           
636    def OnImageRead(self,event):
637        self.CheckNotebook()
638        dlg = wx.FileDialog(self, 'Choose image files', '.', '',\
639        'Any image file (*.tif;*.tiff;*.mar*;*.avg;*.sum;*.img;*.G2img)\
640        |*.tif;*.tiff;*.mar*;*.avg;*.sum;*.img;*.G2img|\
641        Any detector tif (*.tif;*.tiff)|*.tif;*.tiff|\
642        MAR file (*.mar*)|*.mar*|\
643        GE Image (*.avg;*.sum)|*.avg;*.sum|\
644        ADSC Image (*.img)|*.img|\
645        GSAS-II Image (*.G2img)|*.G2img|\
646        All files (*.*)|*.*',
647        wx.OPEN | wx.MULTIPLE|wx.CHANGE_DIR)
648        try:
649            if dlg.ShowModal() == wx.ID_OK:
650                imagefiles = dlg.GetPaths()
651                imagefiles.sort()
652                for imagefile in imagefiles:
653                    Comments,Data,Npix,Image = G2IO.GetImageData(self,imagefile)
654                    if Comments:
655                        Id = self.PatternTree.AppendItem(parent=self.root,text='IMG '+ospath.basename(imagefile))
656                        self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Comments'),Comments)
657                        Imax = np.amax(Image)
658                        Imin = max(0.0,np.amin(Image))          #force positive
659                        if self.imageDefault:
660                            Data = copy.copy(self.imageDefault)
661                            Data['showLines'] = True
662                            Data['ring'] = []
663                            Data['rings'] = []
664                            Data['cutoff'] = 10
665                            Data['pixLimit'] = 20
666                            Data['edgemin'] = 100000000
667                            Data['calibdmin'] = 0.5
668                            Data['calibskip'] = 0
669                            Data['ellipses'] = []
670                            Data['calibrant'] = ''
671                        else:
672                            Data['type'] = 'PWDR'
673                            Data['color'] = 'binary'
674                            Data['tilt'] = 0.0
675                            Data['rotation'] = 0.0
676                            Data['showLines'] = False
677                            Data['ring'] = []
678                            Data['rings'] = []
679                            Data['cutoff'] = 10
680                            Data['pixLimit'] = 20
681                            Data['calibdmin'] = 0.5
682                            Data['calibskip'] = 0
683                            Data['edgemin'] = 100000000
684                            Data['ellipses'] = []
685                            Data['calibrant'] = ''
686                            Data['IOtth'] = [2.0,5.0]
687                            Data['LRazimuth'] = [135,225]
688                            Data['azmthOff'] = 0.0
689                            Data['outChannels'] = 2500
690                            Data['outAzimuths'] = 1
691                            Data['centerAzm'] = False
692                            Data['fullIntegrate'] = False
693                            Data['setRings'] = False
694                            Data['background image'] = ['',1.0]                           
695                        Data['setDefault'] = False
696                        Data['range'] = [(Imin,Imax),[Imin,Imax]]
697                        self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Image Controls'),Data)
698                        Masks = {'Points':[],'Rings':[],'Arcs':[],'Polygons':[],'Thresholds':[(Imin,Imax),[Imin,Imax]]}
699                        self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Masks'),Masks)
700                        self.PatternTree.SetItemPyData(Id,[Npix,imagefile])
701                        self.PickId = Id
702                        self.Image = Id
703                self.PatternTree.SelectItem(G2gd.GetPatternTreeItemId(self,Id,'Image Controls'))             #show last one
704        finally:
705            dlg.Destroy()
706       
707    def OnSnglRead(self,event):
708        self.CheckNotebook()
709        dlg = wx.FileDialog(self, 'Choose file', '.', '', 
710            'hkl files (*.hkl)|*.hkl|All files (*.*)|*.*', 
711            wx.OPEN|wx.CHANGE_DIR)
712        try:
713            if dlg.ShowModal() == wx.ID_OK:
714                filename = dlg.GetPath()
715                wx.BeginBusyCursor()
716                try:
717                    Data = {}
718                    names = ['Type','Lam']
719                    HKLref,HKLmin,HKLmax,FoMax,ifFc = G2IO.GetHKLData(filename)
720                    Id = self.PatternTree.AppendItem(parent=self.root,text='HKLF '+ospath.basename(filename))
721                    self.PatternTree.SetItemPyData(Id,HKLref)
722                    Sub = self.PatternTree.AppendItem(Id,text='Instrument Parameters')
723                    data = ['SXC',1.5428,]
724                    self.PatternTree.SetItemPyData(Sub,[tuple(data),data,names])
725                    Data['Type'] = 'Fosq'
726                    Data['ifFc'] = ifFc
727                    Data['HKLmax'] = HKLmax
728                    Data['HKLmin'] = HKLmin
729                    Data['FoMax'] = FoMax
730                    Data['Zone'] = '001'
731                    Data['Layer'] = 0
732                    Data['Scale'] = 1.0
733                    Data['log-lin'] = 'lin'                   
734                    self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='HKL Plot Controls'),Data)
735                    self.PatternTree.SelectItem(Id)
736                    self.PatternTree.Expand(Id)
737                    self.Sngl = Id
738                finally:
739                    wx.EndBusyCursor()   
740        finally:
741            dlg.Destroy()
742           
743    def CheckNotebook(self):
744        if not G2gd.GetPatternTreeItemId(self,self.root,'Notebook'):
745            sub = self.PatternTree.AppendItem(parent=self.root,text='Notebook')
746            self.PatternTree.SetItemPyData(sub,[''])
747        if not G2gd.GetPatternTreeItemId(self,self.root,'Controls'):
748            sub = self.PatternTree.AppendItem(parent=self.root,text='Controls')
749            self.PatternTree.SetItemPyData(sub,{})
750        if not G2gd.GetPatternTreeItemId(self,self.root,'Covariance'):
751            sub = self.PatternTree.AppendItem(parent=self.root,text='Covariance')
752            self.PatternTree.SetItemPyData(sub,{})
753        if not G2gd.GetPatternTreeItemId(self,self.root,'Constraints'):
754            sub = self.PatternTree.AppendItem(parent=self.root,text='Constraints')
755            self.PatternTree.SetItemPyData(sub,{'Hist':[],'HAP':[],'Phase':[]})
756        if not G2gd.GetPatternTreeItemId(self,self.root,'Restraints'):
757            sub = self.PatternTree.AppendItem(parent=self.root,text='Restraints')
758            self.PatternTree.SetItemPyData(sub,{})
759           
760               
761    class CopyDialog(wx.Dialog):
762        def __init__(self,parent,title,text,data):
763            wx.Dialog.__init__(self,parent,-1,title, 
764                pos=wx.DefaultPosition,style=wx.DEFAULT_DIALOG_STYLE)
765            self.data = data
766            panel = wx.Panel(self)
767            mainSizer = wx.BoxSizer(wx.VERTICAL)
768            topLabl = wx.StaticText(panel,-1,text)
769            mainSizer.Add((10,10),1)
770            mainSizer.Add(topLabl,0,wx.ALIGN_CENTER_VERTICAL|wx.LEFT,10)
771            mainSizer.Add((10,10),1)
772            ncols = len(data)/40+1
773            dataGridSizer = wx.FlexGridSizer(rows=len(data),cols=ncols,hgap=2,vgap=2)
774            for id,item in enumerate(self.data):
775                ckbox = wx.CheckBox(panel,id,item[1])
776                ckbox.Bind(wx.EVT_CHECKBOX,self.OnCopyChange)                   
777                dataGridSizer.Add(ckbox,0,wx.LEFT,10)
778            mainSizer.Add(dataGridSizer,0,wx.EXPAND)
779            OkBtn = wx.Button(panel,-1,"Ok")
780            OkBtn.Bind(wx.EVT_BUTTON, self.OnOk)
781            cancelBtn = wx.Button(panel,-1,"Cancel")
782            cancelBtn.Bind(wx.EVT_BUTTON, self.OnCancel)
783            btnSizer = wx.BoxSizer(wx.HORIZONTAL)
784            btnSizer.Add((20,20),1)
785            btnSizer.Add(OkBtn)
786            btnSizer.Add((20,20),1)
787            btnSizer.Add(cancelBtn)
788            btnSizer.Add((20,20),1)
789           
790            mainSizer.Add(btnSizer,0,wx.EXPAND|wx.BOTTOM|wx.TOP, 10)
791            panel.SetSizer(mainSizer)
792            panel.Fit()
793            self.Fit()
794       
795        def OnCopyChange(self,event):
796            id = event.GetId()
797            self.data[id][0] = self.FindWindowById(id).GetValue()       
798           
799        def OnOk(self,event):
800            parent = self.GetParent()
801            parent.Raise()
802            self.EndModal(wx.ID_OK)             
803            self.Destroy()
804           
805        def OnCancel(self,event):
806            parent = self.GetParent()
807            parent.Raise()
808            self.EndModal(wx.ID_CANCEL)             
809            self.Destroy()
810           
811        def GetData(self):
812            return self.data
813       
814    class SumDialog(wx.Dialog):
815        def __init__(self,parent,title,text,dataType,data):
816            wx.Dialog.__init__(self,parent,-1,title, 
817                pos=wx.DefaultPosition,style=wx.DEFAULT_DIALOG_STYLE)
818            self.data = data
819            panel = wx.Panel(self)
820            mainSizer = wx.BoxSizer(wx.VERTICAL)
821            topLabl = wx.StaticText(panel,-1,text)
822            mainSizer.Add((10,10),1)
823            mainSizer.Add(topLabl,0,wx.ALIGN_CENTER_VERTICAL|wx.LEFT,10)
824            mainSizer.Add((10,10),1)
825            dataGridSizer = wx.FlexGridSizer(rows=len(data),cols=2,hgap=2,vgap=2)
826            for id,item in enumerate(self.data[:-1]):
827                name = wx.TextCtrl(panel,-1,item[1],size=wx.Size(200,20))
828                name.SetEditable(False)
829                scale = wx.TextCtrl(panel,id,'%.3f'%(item[0]),style=wx.TE_PROCESS_ENTER)
830                scale.Bind(wx.EVT_TEXT_ENTER,self.OnScaleChange)
831                scale.Bind(wx.EVT_KILL_FOCUS,self.OnScaleChange)
832                dataGridSizer.Add(scale,0,wx.LEFT,10)
833                dataGridSizer.Add(name,0,wx.RIGHT,10)
834            if dataType:
835                dataGridSizer.Add(wx.StaticText(panel,-1,'Sum result name: '+dataType),0, \
836                    wx.LEFT|wx.TOP|wx.ALIGN_CENTER_VERTICAL,10)
837                self.name = wx.TextCtrl(panel,-1,self.data[-1],size=wx.Size(200,20),style=wx.TE_PROCESS_ENTER)
838                self.name.Bind(wx.EVT_TEXT_ENTER,self.OnNameChange)
839                self.name.Bind(wx.EVT_KILL_FOCUS,self.OnNameChange)
840                dataGridSizer.Add(self.name,0,wx.RIGHT|wx.TOP,10)
841            mainSizer.Add(dataGridSizer,0,wx.EXPAND)
842            OkBtn = wx.Button(panel,-1,"Ok")
843            OkBtn.Bind(wx.EVT_BUTTON, self.OnOk)
844            cancelBtn = wx.Button(panel,-1,"Cancel")
845            cancelBtn.Bind(wx.EVT_BUTTON, self.OnCancel)
846            btnSizer = wx.BoxSizer(wx.HORIZONTAL)
847            btnSizer.Add((20,20),1)
848            btnSizer.Add(OkBtn)
849            btnSizer.Add((20,20),1)
850            btnSizer.Add(cancelBtn)
851            btnSizer.Add((20,20),1)
852           
853            mainSizer.Add(btnSizer,0,wx.EXPAND|wx.BOTTOM|wx.TOP, 10)
854            panel.SetSizer(mainSizer)
855            panel.Fit()
856            self.Fit()
857
858    class ConstraintDialog(wx.Dialog):
859        '''Window to edit Constraint values
860        '''
861        def __init__(self,parent,title,text,data):
862            wx.Dialog.__init__(self,parent,-1,title, 
863                pos=wx.DefaultPosition,style=wx.DEFAULT_DIALOG_STYLE)
864            self.data = data
865            panel = wx.Panel(self)
866            mainSizer = wx.BoxSizer(wx.VERTICAL)
867            topLabl = wx.StaticText(panel,-1,text)
868            mainSizer.Add((10,10),1)
869            mainSizer.Add(topLabl,0,wx.ALIGN_CENTER_VERTICAL|wx.LEFT,10)
870            mainSizer.Add((10,10),1)
871            dataGridSizer = wx.FlexGridSizer(rows=len(data),cols=2,hgap=2,vgap=2)
872            for id,item in enumerate(self.data[:-1]):
873                #name = wx.TextCtrl(panel,-1,item[1],size=wx.Size(200,20))
874                name = wx.StaticText(panel,-1,item[1],size=wx.Size(200,20))
875                #name.SetEditable(False)
876                scale = wx.TextCtrl(panel,id,'%.3f'%(item[0]),style=wx.TE_PROCESS_ENTER)
877                scale.Bind(wx.EVT_TEXT_ENTER,self.OnScaleChange)
878                scale.Bind(wx.EVT_KILL_FOCUS,self.OnScaleChange)
879                dataGridSizer.Add(scale,0,wx.LEFT,10)
880                dataGridSizer.Add(name,0,wx.RIGHT,10)
881            mainSizer.Add(dataGridSizer,0,wx.EXPAND)
882            OkBtn = wx.Button(panel,-1,"Ok")
883            OkBtn.Bind(wx.EVT_BUTTON, self.OnOk)
884            cancelBtn = wx.Button(panel,-1,"Cancel")
885            cancelBtn.Bind(wx.EVT_BUTTON, self.OnCancel)
886            btnSizer = wx.BoxSizer(wx.HORIZONTAL)
887            btnSizer.Add((20,20),1)
888            btnSizer.Add(OkBtn)
889            btnSizer.Add((20,20),1)
890            btnSizer.Add(cancelBtn)
891            btnSizer.Add((20,20),1)
892           
893            mainSizer.Add(btnSizer,0,wx.EXPAND|wx.BOTTOM|wx.TOP, 10)
894            panel.SetSizer(mainSizer)
895            panel.Fit()
896            self.Fit()
897           
898        def OnNameChange(self,event):
899            self.data[-1] = self.name.GetValue() 
900           
901        def OnScaleChange(self,event):
902            id = event.GetId()
903            value = self.FindWindowById(id).GetValue()
904            try:
905                self.data[id][0] = float(value)
906                self.FindWindowById(id).SetValue('%.3f'%(self.data[id][0]))
907            except ValueError:
908                if value and '-' not in value[0]:
909                    print 'bad input - numbers only'
910                    self.FindWindowById(id).SetValue('0.000')
911           
912        def OnOk(self,event):
913            parent = self.GetParent()
914            parent.Raise()
915            self.EndModal(wx.ID_OK)             
916            #self.Destroy() -- do this later, after using GetData
917           
918        def OnCancel(self,event):
919            parent = self.GetParent()
920            parent.Raise()
921            self.EndModal(wx.ID_CANCEL)             
922            #self.Destroy()
923           
924        def GetData(self):
925            return self.data
926           
927    def OnPwdrSum(self,event):
928        TextList = []
929        DataList = []
930        SumList = []
931        Names = []
932        Inst = []
933        SumItemList = []
934        Comments = ['Sum equals: \n']
935        if self.PatternTree.GetCount():
936            item, cookie = self.PatternTree.GetFirstChild(self.root)
937            while item:
938                name = self.PatternTree.GetItemText(item)
939                Names.append(name)
940                if 'PWDR' in name:
941                    TextList.append([0.0,name])
942                    DataList.append(self.PatternTree.GetItemPyData(item)[1])    # (x,y,w,yc,yb,yd)
943                    if not Inst:
944                        Inst = self.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(self,item, 'Instrument Parameters'))
945                item, cookie = self.PatternTree.GetNextChild(self.root, cookie)
946            if len(TextList) < 2:
947                self.ErrorDialog('Not enough data to sum','There must be more than one "PWDR" pattern')
948                return
949            TextList.append('default_sum_name')               
950            dlg = self.SumDialog(self,'Sum data','Enter scale for each pattern in summation','PWDR',TextList)
951            try:
952                if dlg.ShowModal() == wx.ID_OK:
953                    lenX = 0
954                    Xminmax = [0,0]
955                    Xsum = []
956                    Ysum = []
957                    Vsum = []
958                    result = dlg.GetData()
959                    for i,item in enumerate(result[:-1]):
960                        scale,name = item
961                        data = DataList[i]
962                        if scale:
963                            Comments.append("%10.3f %s" % (scale,' * '+name))
964                            x,y,w,yc,yb,yd = data   #numpy arrays!
965                            v = 1./w
966                            if lenX:
967                                if lenX != len(x):
968                                    self.ErrorDialog('Data length error','Data to be summed must have same number of points'+ \
969                                        '\nExpected:'+str(lenX)+ \
970                                        '\nFound:   '+str(len(x))+'\nfor '+name)
971                                    return
972                            else:
973                                lenX = len(x)
974                            if Xminmax[1]:
975                                if Xminmax != [x[0],x[-1]]:
976                                    self.ErrorDialog('Data range error','Data to be summed must span same range'+ \
977                                        '\nExpected:'+str(Xminmax[0])+' '+str(Xminmax[1])+ \
978                                        '\nFound:   '+str(x[0])+' '+str(x[-1])+'\nfor '+name)
979                                    return
980                                else:
981                                    for j,yi in enumerate(y):
982                                         Ysum[j] += scale*yi
983                                         Vsum[j] += abs(scale)*v[j]
984                            else:
985                                Xminmax = [x[0],x[-1]]
986                                YCsum = YBsum = YDsum = [0.0 for i in range(lenX)]
987                                for j,yi in enumerate(y):
988                                    Xsum.append(x[j])
989                                    Ysum.append(scale*yi)
990                                    Vsum.append(abs(scale*v[j]))
991                    Wsum = 1./np.array(Vsum)
992                    outname = 'PWDR '+result[-1]
993                    Id = 0
994                    if outname in Names:
995                        dlg2 = wx.MessageDialog(self,'Overwrite data?','Duplicate data name',wx.OK|wx.CANCEL)
996                        try:
997                            if dlg2.ShowModal() == wx.ID_OK:
998                                Id = G2gd.GetPatternTreeItemId(self,self.root,name)
999                                self.PatternTree.Delete(Id)
1000                        finally:
1001                            dlg2.Destroy()
1002                    Id = self.PatternTree.AppendItem(parent=self.root,text=outname)
1003                    if Id:
1004                        Sample = G2pdG.SetDefaultSample()
1005                        self.PatternTree.SetItemPyData(Id,[[''],[np.array(Xsum),np.array(Ysum),np.array(Wsum),
1006                            np.array(YCsum),np.array(YBsum),np.array(YDsum)]])
1007                        self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Comments'),Comments)                   
1008                        self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Limits'),[tuple(Xminmax),Xminmax])
1009                        self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Background'),[['chebyschev',True,3,1.0,0.0,0.0],
1010                            {'nDebye':0,'debyeTerms':[],'nPeaks':0,'peaksList':[]}])
1011                        self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Instrument Parameters'),Inst)
1012                        self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Sample Parameters'),Sample)
1013                        self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Peak List'),[])
1014                        self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Index Peak List'),[])
1015                        self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Unit Cells List'),[])             
1016                        self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Reflection Lists'),{})             
1017                        self.PatternTree.SelectItem(Id)
1018                        self.PatternTree.Expand(Id)
1019                   
1020            finally:
1021                dlg.Destroy()
1022
1023    def OnImageSum(self,event):
1024        TextList = []
1025        DataList = []
1026        SumList = []
1027        Names = []
1028        Inst = []
1029        SumItemList = []
1030        Comments = ['Sum equals: \n']
1031        if self.PatternTree.GetCount():
1032            item, cookie = self.PatternTree.GetFirstChild(self.root)
1033            while item:
1034                name = self.PatternTree.GetItemText(item)
1035                Names.append(name)
1036                if 'IMG' in name:
1037                    TextList.append([0.0,name])
1038                    DataList.append(self.PatternTree.GetItemPyData(item))        #Size,Image
1039                    Data = self.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(self,item,'Image Controls'))
1040                item, cookie = self.PatternTree.GetNextChild(self.root, cookie)
1041            if len(TextList) < 2:
1042                self.ErrorDialog('Not enough data to sum','There must be more than one "IMG" pattern')
1043                return
1044            TextList.append('default_sum_name')               
1045            dlg = self.SumDialog(self,'Sum data','Enter scale for each image in summation','IMG',TextList)
1046            try:
1047                if dlg.ShowModal() == wx.ID_OK:
1048                    imSize = 0
1049                    result = dlg.GetData()
1050                    First = True
1051                    Found = False
1052                    for i,item in enumerate(result[:-1]):
1053                        scale,name = item
1054                        data = DataList[i]
1055                        if scale:
1056                            Found = True                               
1057                            Comments.append("%10.3f %s" % (scale,' * '+name))
1058                            Npix,imagefile = data
1059                            image = G2IO.GetImageData(self,imagefile,imageOnly=True)
1060                            if First:
1061                                newImage = np.zeros_like(image)
1062                                First = False
1063                            if imSize:
1064                                if imSize != Npix:
1065                                    self.ErrorDialog('Image size error','Images to be summed must be same size'+ \
1066                                        '\nExpected:'+str(imSize)+ \
1067                                        '\nFound:   '+str(Npix)+'\nfor '+name)
1068                                    return
1069                                newImage = newImage+scale*image
1070                            else:
1071                                imSize = Npix
1072                                newImage = newImage+scale*image
1073                            del(image)
1074                    if not Found:
1075                        self.ErrorDialog('Image sum error','No nonzero image multipliers found')
1076                        return
1077                       
1078                    newImage = np.asfarray(newImage,dtype=np.float32)                       
1079                    outname = 'IMG '+result[-1]
1080                    Id = 0
1081                    if outname in Names:
1082                        dlg2 = wx.MessageDialog(self,'Overwrite data?','Duplicate data name',wx.OK|wx.CANCEL)
1083                        try:
1084                            if dlg2.ShowModal() == wx.ID_OK:
1085                                Id = G2gd.GetPatternTreeItemId(self,self.root,name)
1086                        finally:
1087                            dlg2.Destroy()
1088                    else:
1089                        Id = self.PatternTree.AppendItem(parent=self.root,text=outname)
1090                    if Id:
1091                        dlg = wx.FileDialog(self, 'Choose sum image filename', '.', '', 
1092                            'G2img files (*.G2img)|*.G2img', 
1093                            wx.SAVE|wx.FD_OVERWRITE_PROMPT|wx.CHANGE_DIR)
1094                        if dlg.ShowModal() == wx.ID_OK:
1095                            newimagefile = dlg.GetPath()
1096                            newimagefile = G2IO.FileDlgFixExt(dlg,newimagefile)
1097                            G2IO.PutG2Image(newimagefile,Comments,Data,Npix,newImage)
1098                            Imax = np.amax(newImage)
1099                            Imin = np.amin(newImage)
1100                            newImage = []
1101                            self.PatternTree.SetItemPyData(Id,[imSize,newimagefile])
1102                            self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Comments'),Comments)
1103                        del(newImage)
1104                        if self.imageDefault:
1105                            Data = copy.copy(self.imageDefault)
1106                        Data['showLines'] = True
1107                        Data['ring'] = []
1108                        Data['rings'] = []
1109                        Data['cutoff'] = 10
1110                        Data['pixLimit'] = 20
1111                        Data['ellipses'] = []
1112                        Data['calibrant'] = ''
1113                        Data['range'] = [(Imin,Imax),[Imin,Imax]]
1114                        self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Image Controls'),Data)                                           
1115                        Masks = {'Points':[],'Rings':[],'Arcs':[],'Polygons':[],'Thresholds':[(Imin,Imax),[Imin,Imax]]}
1116                        self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Masks'),Masks)
1117                        self.PatternTree.SelectItem(Id)
1118                        self.PatternTree.Expand(Id)
1119                        self.PickId = G2gd.GetPatternTreeItemId(self,self.root,outname)
1120                        self.Image = self.PickId
1121            finally:
1122                dlg.Destroy()
1123                     
1124    def OnAddPhase(self,event):
1125        if not G2gd.GetPatternTreeItemId(self,self.root,'Phases'):
1126            sub = self.PatternTree.AppendItem(parent=self.root,text='Phases')
1127        else:
1128            sub = G2gd.GetPatternTreeItemId(self,self.root,'Phases')
1129        PhaseName = ''
1130        dlg = wx.TextEntryDialog(None,'Enter a name for this phase','Phase Name Entry','New phase',
1131            style=wx.OK)
1132        if dlg.ShowModal() == wx.ID_OK:
1133            PhaseName = dlg.GetValue()
1134        dlg.Destroy()
1135        sub = self.PatternTree.AppendItem(parent=sub,text=PhaseName)
1136        E,SGData = G2spc.SpcGroup('P 1')
1137        self.PatternTree.SetItemPyData(sub,G2IO.SetNewPhase(Name=PhaseName,SGData=SGData))
1138       
1139    def OnDeletePhase(self,event):
1140        #Hmm, also need to delete this phase from Reflection Lists for each PWDR histogram
1141        if self.dataFrame:
1142            self.dataFrame.Clear() 
1143        TextList = []
1144        DelList = []
1145        DelItemList = []
1146        if G2gd.GetPatternTreeItemId(self,self.root,'Phases'):
1147            sub = G2gd.GetPatternTreeItemId(self,self.root,'Phases')
1148        else:
1149            return
1150        if sub:
1151            item, cookie = self.PatternTree.GetFirstChild(sub)
1152            while item:
1153                TextList.append(self.PatternTree.GetItemText(item))
1154                item, cookie = self.PatternTree.GetNextChild(sub, cookie)               
1155            dlg = wx.MultiChoiceDialog(self, 'Which phase to delete?', 'Delete phase', TextList, wx.CHOICEDLG_STYLE)
1156            try:
1157                if dlg.ShowModal() == wx.ID_OK:
1158                    result = dlg.GetSelections()
1159                    for i in result: DelList.append([i,TextList[i]])
1160                    item, cookie = self.PatternTree.GetFirstChild(sub)
1161                    i = 0
1162                    while item:
1163                        if [i,self.PatternTree.GetItemText(item)] in DelList: DelItemList.append(item)
1164                        item, cookie = self.PatternTree.GetNextChild(sub, cookie)
1165                        i += 1
1166                    for item in DelItemList:
1167                        name = self.PatternTree.GetItemText(item)
1168                        self.PatternTree.Delete(item)
1169                        self.G2plotNB.Delete(name)
1170                    item, cookie = self.PatternTree.GetFirstChild(self.root)
1171                    while item:
1172                        name = self.PatternTree.GetItemText(item)
1173                        if 'PWDR' in name:
1174                            Id = G2gd.GetPatternTreeItemId(self,item, 'Reflection Lists')
1175                            refList = self.PatternTree.GetItemPyData(Id)
1176                            for i,item in DelList:
1177                                del(refList[item])
1178                            self.PatternTree.SetItemPyData(Id,refList)
1179                        item, cookie = self.PatternTree.GetNextChild(self.root, cookie)
1180            finally:
1181                dlg.Destroy()
1182               
1183    def OnRenameData(self,event):
1184        name = self.PatternTree.GetItemText(self.PickId)     
1185        if 'PWDR' in name or 'HKLF' in name or 'IMG' in name:
1186            dataType = name[:name.index(' ')+1]                 #includes the ' '
1187            dlg = wx.TextEntryDialog(self,'Data name: '+dataType,'Change data name',
1188                defaultValue=name[name.index(' ')+1:])
1189            try:
1190                if dlg.ShowModal() == wx.ID_OK:
1191                    self.PatternTree.SetItemText(self.PickId,dataType+dlg.GetValue())
1192            finally:
1193                dlg.Destroy()
1194       
1195    def GetFileList(self,fileType,skip=None):        #potentially useful?
1196        fileList = []
1197        Source = ''
1198        id, cookie = self.PatternTree.GetFirstChild(self.root)
1199        while id:
1200            name = self.PatternTree.GetItemText(id)
1201            if fileType in name:
1202                if id == skip:
1203                    Source = name
1204                else:
1205                    fileList.append([False,name,id])
1206            id, cookie = self.PatternTree.GetNextChild(self.root, cookie)
1207        if skip:
1208            return fileList,Source
1209        else:
1210            return fileList
1211           
1212    def OnDataDelete(self, event):
1213        TextList = ['All Data']
1214        DelList = []
1215        DelItemList = []
1216        ifPWDR = False
1217        ifIMG = False
1218        ifHKLF = False
1219        ifPDF = False
1220        if self.PatternTree.GetCount():
1221            item, cookie = self.PatternTree.GetFirstChild(self.root)
1222            while item:
1223                name = self.PatternTree.GetItemText(item)
1224                if name not in ['Notebook','Controls','Covariance','Constraints','Restraints','Phases']:
1225                    if 'PWDR' in name: ifPWDR = True
1226                    if 'IMG' in name: ifIMG = True
1227                    if 'HKLF' in name: ifHKLF = True
1228                    if 'PDF' in name: ifPDF = True
1229                    TextList.append(name)
1230                item, cookie = self.PatternTree.GetNextChild(self.root, cookie)
1231            if ifPWDR: TextList.insert(1,'All PWDR')
1232            if ifIMG: TextList.insert(1,'All IMG')
1233            if ifHKLF: TextList.insert(1,'All HKLF')
1234            if ifPDF: TextList.insert(1,'All PDF')               
1235            dlg = wx.MultiChoiceDialog(self, 'Which data to delete?', 'Delete data', TextList, wx.CHOICEDLG_STYLE)
1236            try:
1237                if dlg.ShowModal() == wx.ID_OK:
1238                    result = dlg.GetSelections()
1239                    for i in result: DelList.append(TextList[i])
1240                    if 'All Data' in DelList:
1241                        DelList = [item for item in TextList if item[:3] != 'All']
1242                    elif 'All PWDR' in DelList:
1243                        DelList = [item for item in TextList if item[:4] == 'PWDR']
1244                    elif 'All IMG' in DelList:
1245                        DelList = [item for item in TextList if item[:3] == 'IMG']
1246                    elif 'All HKLF' in DelList:
1247                        DelList = [item for item in TextList if item[:4] == 'HKLF']
1248                    elif 'All PDF' in DelList:
1249                        DelList = [item for item in TextList if item[:3] == 'PDF']
1250                    item, cookie = self.PatternTree.GetFirstChild(self.root)
1251                    while item:
1252                        if self.PatternTree.GetItemText(item) in DelList: DelItemList.append(item)
1253                        item, cookie = self.PatternTree.GetNextChild(self.root, cookie)
1254                    for item in DelItemList:
1255                        self.PatternTree.Delete(item)
1256                    G2plt.PlotPatterns(self,True)                        #so plot gets updated
1257            finally:
1258                dlg.Destroy()
1259
1260    def OnFileOpen(self, event):
1261        result = ''
1262        Id = 0
1263        if self.PatternTree.GetChildrenCount(self.root,False):
1264            if self.dataFrame:
1265                self.dataFrame.Clear() 
1266            dlg = wx.MessageDialog(self, 'Overwrite?','Project exists!',  wx.OK | wx.CANCEL)
1267            try:
1268                result = dlg.ShowModal()
1269                if result == wx.ID_OK:
1270                    self.PatternTree.DeleteChildren(self.root)
1271                    self.GSASprojectfile = ''
1272#                    self.PatternTree.DeleteChildren(self.root)
1273                    if self.HKL: self.HKL = []
1274                    if self.G2plotNB.plotList:
1275                        self.G2plotNB.clear()
1276            finally:
1277                dlg.Destroy()
1278        if result != wx.ID_CANCEL:   
1279            if self.dataDisplay: self.dataDisplay.Destroy()
1280            dlg = wx.FileDialog(self, 'Choose GSAS-II project file', '.', '', 
1281                'GSAS-II project file (*.gpx)|*.gpx',wx.OPEN|wx.CHANGE_DIR)
1282            try:
1283                if dlg.ShowModal() == wx.ID_OK:
1284                    self.GSASprojectfile = dlg.GetPath()
1285                    self.GSASprojectfile = G2IO.FileDlgFixExt(dlg,self.GSASprojectfile)
1286                    self.dirname = dlg.GetDirectory()
1287                    G2IO.ProjFileOpen(self)
1288                    self.PatternTree.SetItemText(self.root,'Loaded Data: '+self.GSASprojectfile)
1289                    self.PatternTree.Expand(self.root)
1290                    self.HKL = []
1291                    item, cookie = self.PatternTree.GetFirstChild(self.root)
1292                    while item and not Id:
1293                        name = self.PatternTree.GetItemText(item)
1294                        if name[:4] in ['PWDR','HKLF','IMG ','PDF ']:
1295                            Id = item
1296                        elif name == 'Controls':
1297                            data = self.PatternTree.GetItemPyData(item)
1298                            if data:
1299                                self.Refine.Enable(True)
1300                                self.SeqRefine.Enable(True)
1301                        item, cookie = self.PatternTree.GetNextChild(self.root, cookie)               
1302                    if Id:
1303                        self.PatternTree.SelectItem(Id)
1304                    self.CheckNotebook()
1305            finally:
1306                dlg.Destroy()
1307
1308
1309    def OnFileClose(self, event):
1310        if self.dataFrame:
1311            self.dataFrame.Clear()
1312            self.dataFrame.SetLabel('GSAS-II data display') 
1313        dlg = wx.MessageDialog(self, 'Save current project?', ' ', wx.YES | wx.NO | wx.CANCEL)
1314        try:
1315            result = dlg.ShowModal()
1316            if result == wx.ID_OK:
1317                self.OnFileSaveMenu(event)
1318            if result != wx.ID_CANCEL:
1319                self.GSASprojectfile = ''
1320                self.PatternTree.SetItemText(self.root,'Loaded Data: ')
1321                self.PatternTree.DeleteChildren(self.root)
1322                if self.HKL: self.HKL = []
1323                if self.G2plotNB.plotList:
1324                    self.G2plotNB.clear()
1325        finally:
1326            dlg.Destroy()
1327
1328    def OnFileSave(self, event):
1329        if self.GSASprojectfile: 
1330            self.PatternTree.SetItemText(self.root,'Loaded Data: '+self.GSASprojectfile)
1331            G2IO.ProjFileSave(self)
1332        else:
1333            self.OnFileSaveas(event)
1334
1335    def OnFileSaveas(self, event):
1336        dlg = wx.FileDialog(self, 'Choose GSAS-II project file name', '.', '', 
1337            'GSAS-II project file (*.gpx)|*.gpx',wx.FD_SAVE|wx.FD_OVERWRITE_PROMPT|wx.CHANGE_DIR)
1338        try:
1339            if dlg.ShowModal() == wx.ID_OK:
1340                self.GSASprojectfile = dlg.GetPath()
1341                self.GSASprojectfile = G2IO.FileDlgFixExt(dlg,self.GSASprojectfile)
1342                self.PatternTree.SetItemText(self.root,'Loaded Data: '+self.GSASprojectfile)
1343                G2IO.ProjFileSave(self)
1344                self.dirname = dlg.GetDirectory()
1345        finally:
1346            dlg.Destroy()
1347
1348    def ExitMain(self, event):
1349        if self.undofile:
1350            os.remove(self.undofile)
1351        sys.exit()
1352       
1353    def OnFileExit(self, event):
1354        if self.dataFrame:
1355            self.dataFrame.Clear() 
1356            self.dataFrame.Destroy()
1357        self.Close()
1358       
1359    def OnImportPattern(self,event):
1360        dlg = wx.FileDialog(self, 'Choose nonGSAS powder file', '.', '', 
1361            '(*.*)|*.*',wx.OPEN|wx.CHANGE_DIR)
1362        try:
1363            if dlg.ShowModal() == wx.ID_OK:
1364                self.powderfile = dlg.GetPath()
1365        finally:
1366            dlg.Destroy()
1367           
1368    def OnImportHKL(self,event):
1369        dlg = wx.FileDialog(self, 'Choose structure factor file', '.', '', 
1370            '(*.*)|*.*',wx.OPEN|wx.CHANGE_DIR)
1371        try:
1372            if dlg.ShowModal() == wx.ID_OK:
1373                self.HKLfile = dlg.GetPath()
1374        finally:
1375            dlg.Destroy()
1376       
1377    def OnExportPatterns(self,event):
1378        names = ['All']
1379        exports = []
1380        item, cookie = self.PatternTree.GetFirstChild(self.root)
1381        while item:
1382            name = self.PatternTree.GetItemText(item)
1383            if 'PWDR' in name:
1384                names.append(name)
1385            item, cookie = self.PatternTree.GetNextChild(self.root, cookie)
1386        if names:
1387            dlg = wx.MultiChoiceDialog(self,'Select','Powder patterns to export',names)
1388            if dlg.ShowModal() == wx.ID_OK:
1389                sel = dlg.GetSelections()
1390                if sel[0] == 0:
1391                    exports = names[1:]
1392                else:
1393                    for x in sel:
1394                        exports.append(names[x])
1395            dlg.Destroy()
1396        if exports:
1397            dlg = wx.FileDialog(self, 'Choose output powder file name', '.', '', 
1398                'GSAS fxye file (*.fxye)|*.fxye|xye file (*.xye)|*.xye',
1399                wx.FD_SAVE|wx.FD_OVERWRITE_PROMPT|wx.CHANGE_DIR)
1400            try:
1401                if dlg.ShowModal() == wx.ID_OK:
1402                    powderfile = dlg.GetPath()
1403                    powderfile = G2IO.FileDlgFixExt(dlg,powderfile)
1404                    if 'fxye' in powderfile:
1405                        G2IO.powderFxyeSave(self,exports,powderfile)
1406                    else:       #just xye
1407                        G2IO.powderXyeSave(self,exports,powderfile)
1408            finally:
1409                dlg.Destroy()
1410       
1411    def OnExportPeakList(self,event):
1412        dlg = wx.FileDialog(self, 'Choose output peak list file name', '.', '', 
1413            '(*.*)|*.*',wx.FD_SAVE|wx.FD_OVERWRITE_PROMPT|wx.CHANGE_DIR)
1414        try:
1415            if dlg.ShowModal() == wx.ID_OK:
1416                self.peaklistfile = dlg.GetPath()
1417                self.peaklistfile = G2IO.FileDlgFixExt(dlg,self.peaklistfile)
1418                file = open(self.peaklistfile,'w')               
1419                item, cookie = self.PatternTree.GetFirstChild(self.root)
1420                while item:
1421                    name = self.PatternTree.GetItemText(item)
1422                    if 'PWDR' in name:
1423                        item2, cookie2 = self.PatternTree.GetFirstChild(item)
1424                        while item2:
1425                            name2 = self.PatternTree.GetItemText(item2)
1426                            if name2 == 'Peak List':
1427                                peaks = self.PatternTree.GetItemPyData(item2)
1428                                file.write("%s \n" % (name+' Peak List'))               
1429                                for peak in peaks:
1430                                    file.write("%10.4f %12.2f %10.3f %10.3f \n" % \
1431                                        (peak[0],peak[2],peak[4],peak[6]))
1432                            item2, cookie2 = self.PatternTree.GetNextChild(item, cookie2)                           
1433                    item, cookie = self.PatternTree.GetNextChild(self.root, cookie)                           
1434                file.close()
1435        finally:
1436            dlg.Destroy()
1437       
1438    def OnExportHKL(self,event):
1439        event.Skip()
1440       
1441    def OnExportPDF(self,event):
1442        #need S(Q) and G(R) to be saved here - probably best from selection?
1443        names = ['All']
1444        exports = []
1445        item, cookie = self.PatternTree.GetFirstChild(self.root)
1446        while item:
1447            name = self.PatternTree.GetItemText(item)
1448            if 'PDF' in name:
1449                names.append(name)
1450            item, cookie = self.PatternTree.GetNextChild(self.root, cookie)
1451        if names:
1452            dlg = wx.MultiChoiceDialog(self,'Select','PDF patterns to export',names)
1453            if dlg.ShowModal() == wx.ID_OK:
1454                sel = dlg.GetSelections()
1455                if sel[0] == 0:
1456                    exports = names[1:]
1457                else:
1458                    for x in sel:
1459                        exports.append(names[x])
1460            dlg.Destroy()
1461        if exports:
1462            G2IO.PDFSave(self,exports)
1463       
1464    def OnExportPhase(self,event):
1465        event.Skip()
1466       
1467    def OnExportCIF(self,event):
1468        event.Skip()
1469
1470    def OnMakePDFs(self,event):
1471        tth2q = lambda t,w:4.0*math.pi*sind(t/2.0)/w
1472        TextList = ['All PWDR']
1473        PDFlist = []
1474        Names = []
1475        if self.PatternTree.GetCount():
1476            id, cookie = self.PatternTree.GetFirstChild(self.root)
1477            while id:
1478                name = self.PatternTree.GetItemText(id)
1479                Names.append(name)
1480                if 'PWDR' in name:
1481                    TextList.append(name)
1482                id, cookie = self.PatternTree.GetNextChild(self.root, cookie)
1483            if len(TextList) == 1:
1484                self.ErrorDialog('Nothing to make PDFs for','There must be at least one "PWDR" pattern')
1485                return
1486            dlg = wx.MultiChoiceDialog(self,'Make PDF controls','Make PDF controls for:',TextList, wx.CHOICEDLG_STYLE)
1487            try:
1488                if dlg.ShowModal() == wx.ID_OK:
1489                    result = dlg.GetSelections()
1490                    for i in result: PDFlist.append(TextList[i])
1491                    if 0 in result:
1492                        PDFlist = [item for item in TextList if item[:4] == 'PWDR']                       
1493                    for item in PDFlist:
1494                        PWDRname = item[4:]
1495                        Id = self.PatternTree.AppendItem(parent=self.root,text='PDF '+PWDRname)
1496                        Data = {
1497                            'Sample':{'Name':item,'Mult':1.0,'Add':0.0},
1498                            'Sample Bkg.':{'Name':'','Mult':-1.0,'Add':0.0},
1499                            'Container':{'Name':'','Mult':-1.0,'Add':0.0},
1500                            'Container Bkg.':{'Name':'','Mult':-1.0,'Add':0.0},'ElList':{},
1501                            'Geometry':'Cylinder','Diam':1.0,'Pack':0.50,'Form Vol':10.0,
1502                            'DetType':'Image plate','ObliqCoeff':0.2,'Ruland':0.025,'QScaleLim':[0,100],
1503                            'Lorch':True,}
1504                        self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='PDF Controls'),Data)
1505                        self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='I(Q)'+PWDRname),[])       
1506                        self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='S(Q)'+PWDRname),[])       
1507                        self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='F(Q)'+PWDRname),[])       
1508                        self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='G(R)'+PWDRname),[])       
1509                self.ExportPDF.Enable(True)
1510            finally:
1511                dlg.Destroy()
1512               
1513    def GetPWDRdatafromTree(self,PWDRname):
1514        ''' Returns powder data from GSASII tree
1515        input:
1516            PWDRname = powder histogram name as obtained from GetHistogramNames
1517        return:
1518            PWDRdata = powder data dictionary with:
1519                Data - powder data arrays, Limits, Instrument Parameters, Sample Parameters           
1520        '''
1521        PWDRdata = {}
1522        PWDRdata['Data'] = self.PatternTree.GetItemPyData(PWDRname)[1]          #powder data arrays
1523        PWDRdata['Limits'] = self.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(self,PWDRname,'Limits'))
1524        PWDRdata['Background'] = self.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(self,PWDRname,'Background'))
1525        PWDRdata['Instrument Parameters'] = self.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(self,PWDRname,'Instrument Parameters'))
1526        PWDRdata['Sample Parameters'] = self.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(self,PWDRname,'Sample Parameters'))
1527        PWDRdata['Reflection Lists'] = self.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(self,PWDRname,'Reflection Lists'))
1528        return PWDRdata
1529
1530    def GetHKLFdatafromTree(self,HKLFname):
1531        ''' Returns single crystal data from GSASII tree
1532        input:
1533            HKLFname = single crystal histogram name as obtained from GetHistogramNames
1534        return:
1535            HKLFdata = single crystal data list of reflections: for each reflection:
1536                HKLF = [np.array([h,k,l]),FoSq,sigFoSq,FcSq,Fcp,Fcpp,phase]
1537        '''
1538        HKLFdata = []
1539        while True:
1540            data = self.PatternTree.GetItemPyData(HKLFname)
1541            datum = data[0]
1542            if datum[0] == HKLFname:
1543                HKLFdata = datum[1:][0]
1544        return HKLFdata
1545                   
1546    def GetUsedHistogramsAndPhasesfromTree(self):
1547        ''' Returns all histograms that are found in any phase
1548        and any phase that uses a histogram
1549        return:
1550            Histograms = dictionary of histograms as {name:data,...}
1551            Phases = dictionary of phases that use histograms
1552        '''
1553        phaseData = {}
1554        if G2gd.GetPatternTreeItemId(self,self.root,'Phases'):
1555            sub = G2gd.GetPatternTreeItemId(self,self.root,'Phases')
1556        else:
1557            print 'no phases to be refined'
1558            return
1559        if sub:
1560            item, cookie = self.PatternTree.GetFirstChild(sub)
1561            while item:
1562                phaseData[self.PatternTree.GetItemText(item)] =  self.PatternTree.GetItemPyData(item)               
1563                item, cookie = self.PatternTree.GetNextChild(sub, cookie)               
1564        Histograms = {}
1565        Phases = {}
1566        pId = 0
1567        hId = 0
1568        for phase in phaseData:
1569            Phase = phaseData[phase]
1570            if Phase['Histograms']:
1571                if phase not in Phases:
1572                    Phase['pId'] = pId
1573                    pId += 1
1574                    Phases[phase] = Phase
1575                for hist in Phase['Histograms']:
1576                    if hist not in Histograms:
1577                        item = G2gd.GetPatternTreeItemId(self,self.root,hist)
1578                        if 'PWDR' in hist[:4]: 
1579                            Histograms[hist] = self.GetPWDRdatafromTree(item)
1580                        elif 'HKLF' in hist[:4]:
1581                            Histograms[hist] = self.GetHKLFdatafromTree(item)
1582                        #future restraint, etc. histograms here           
1583                        Histograms[hist]['hId'] = hId
1584                        hId += 1
1585        return Histograms,Phases
1586       
1587    class ViewParmDialog(wx.Dialog):
1588        def __init__(self,parent,title,parmDict):
1589            wx.Dialog.__init__(self,parent,-1,title,size=(300,430),
1590                pos=wx.DefaultPosition,style=wx.DEFAULT_DIALOG_STYLE)
1591            panel = wx.Panel(self,size=(300,430))
1592            parmNames = parmDict.keys()
1593            parmNames.sort()
1594            parmText = ' p:h:Parameter       refine?              value\n'
1595            for name in parmNames:
1596                parmData = parmDict[name]
1597                try:
1598                    parmText += ' %s \t%12.4g \n'%(name.ljust(19)+'\t'+parmData[1],parmData[0])
1599                except TypeError:
1600                    pass
1601            parmTable = wx.TextCtrl(panel,-1,parmText,
1602                style=wx.TE_MULTILINE|wx.TE_READONLY,size=(290,400))
1603            mainSizer = wx.BoxSizer(wx.VERTICAL)
1604            mainSizer.Add(parmTable)
1605            panel.SetSizer(mainSizer)
1606                           
1607    def OnViewLSParms(self,event):
1608        parmDict = {}
1609        Histograms,Phases = self.GetUsedHistogramsAndPhasesfromTree()
1610        Natoms,phaseVary,phaseDict,pawleyLookup,FFtable,BLtable = G2str.GetPhaseData(Phases,Print=False)       
1611        hapVary,hapDict,controlDict = G2str.GetHistogramPhaseData(Phases,Histograms,Print=False)
1612        histVary,histDict,controlDict = G2str.GetHistogramData(Histograms,Print=False)
1613        varyList = phaseVary+hapVary+histVary
1614        parmDict.update(phaseDict)
1615        parmDict.update(hapDict)
1616        parmDict.update(histDict)
1617        for parm in parmDict:
1618            if parm.split(':')[-1] in ['Azimuth','Gonio. radius','Lam1','Lam2','Omega','Chi','Phi']:
1619                parmDict[parm] = [parmDict[parm],' ']
1620            elif parm.split(':')[-2] in ['Ax','Ay','Az','SHmodel','SHord']:
1621                parmDict[parm] = [parmDict[parm],' ']
1622            elif parm in varyList:
1623                parmDict[parm] = [parmDict[parm],'True']
1624            else:
1625                parmDict[parm] = [parmDict[parm],'False']
1626        parmDict[' Num refined'] = [len(varyList),'']
1627        dlg = self.ViewParmDialog(self,'Parameters for least squares',parmDict)
1628        try:
1629            if dlg.ShowModal() == wx.ID_OK:
1630                print 'do something with changes?? - No!'
1631        finally:
1632            dlg.Destroy()
1633       
1634    def OnRefine(self,event):
1635        self.OnFileSave(event)
1636        #works - but it'd be better if it could restore plots
1637        dlg = wx.ProgressDialog('Residual','Powder profile Rwp =',101.0, 
1638            style = wx.PD_ELAPSED_TIME|wx.PD_AUTO_HIDE|wx.PD_CAN_ABORT)
1639        screenSize = wx.ClientDisplayRect()
1640        Size = dlg.GetSize()
1641        Size = (int(Size[0]*1.2),Size[1]) # increase size a bit along x
1642        dlg.SetPosition(wx.Point(screenSize[2]-Size[0]-305,screenSize[1]+5))
1643        dlg.SetSize(Size)
1644        Rwp = 100.00
1645        try:
1646            Rwp = G2str.Refine(self.GSASprojectfile,dlg)
1647        finally:
1648            dlg.Destroy()       
1649        dlg = wx.MessageDialog(self,'Load new result?','Refinement results, Rwp =%.3f'%(Rwp),wx.OK|wx.CANCEL)
1650        try:
1651            if dlg.ShowModal() == wx.ID_OK:
1652                Id = 0
1653                self.PatternTree.DeleteChildren(self.root)
1654                if self.HKL: self.HKL = []
1655                if self.G2plotNB.plotList:
1656                    self.G2plotNB.clear()
1657                G2IO.ProjFileOpen(self)
1658                item, cookie = self.PatternTree.GetFirstChild(self.root)
1659                while item and not Id:
1660                    name = self.PatternTree.GetItemText(item)
1661                    if name[:4] in ['PWDR','HKLF']:
1662                        Id = item
1663                    item, cookie = self.PatternTree.GetNextChild(self.root, cookie)               
1664                if Id:
1665                    self.PatternTree.SelectItem(Id)
1666        finally:
1667            dlg.Destroy()
1668
1669    def OnSeqRefine(self,event):
1670        Id = G2gd.GetPatternTreeItemId(self,self.root,'Sequental results')
1671        if not Id:
1672            Id = self.PatternTree.AppendItem(self.root,text='Sequental results')
1673            self.PatternTree.SetItemPyData(Id,{})           
1674        self.OnFileSave(event)
1675        dlg = wx.ProgressDialog('Residual for histogram 0','Powder profile Rwp =',101.0, 
1676            style = wx.PD_ELAPSED_TIME|wx.PD_AUTO_HIDE|wx.PD_CAN_ABORT)
1677        screenSize = wx.ClientDisplayRect()
1678        Size = dlg.GetSize()
1679        Size = (int(Size[0]*1.2),Size[1]) # increase size a bit along x
1680        dlg.SetPosition(wx.Point(screenSize[2]-Size[0]-305,screenSize[1]+5))
1681        dlg.SetSize(Size)
1682        try:
1683            G2str.SeqRefine(self.GSASprojectfile,dlg)
1684        finally:
1685            dlg.Destroy()       
1686        dlg = wx.MessageDialog(self,'Load new result?','Refinement results',wx.OK|wx.CANCEL)
1687        try:
1688            if dlg.ShowModal() == wx.ID_OK:
1689                Id = 0
1690                self.PatternTree.DeleteChildren(self.root)
1691                if self.HKL: self.HKL = []
1692                if self.G2plotNB.plotList:
1693                    self.G2plotNB.clear()
1694                G2IO.ProjFileOpen(self)
1695                item, cookie = self.PatternTree.GetFirstChild(self.root)
1696                while item and not Id:
1697                    name = self.PatternTree.GetItemText(item)
1698                    if name[:4] in ['PWDR','HKLF']:
1699                        Id = item
1700                    item, cookie = self.PatternTree.GetNextChild(self.root, cookie)               
1701                if Id:
1702                    self.PatternTree.SelectItem(Id)
1703        finally:
1704            dlg.Destroy()
1705       
1706    def ErrorDialog(self,title,message):
1707        dlg = wx.MessageDialog(self, message, title,  wx.OK)
1708        try:
1709            result = dlg.ShowModal()
1710        finally:
1711            dlg.Destroy()
1712
1713class GSASIImain(wx.App):
1714    def OnInit(self):
1715        self.main = GSASII(None)
1716        self.main.Show()
1717        self.SetTopWindow(self.main)
1718        return True
1719
1720def main():
1721    application = GSASIImain(0)
1722    if wxInspector: wxeye.InspectionTool().Show()
1723
1724    #application.main.OnRefine(None)
1725    application.MainLoop()
1726   
1727if __name__ == '__main__':
1728    main()
Note: See TracBrowser for help on using the repository browser.