source: trunk/GSASII.py @ 547

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

redo constraints input & editing; change file overdef in G2struct

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