source: trunk/GSASII.py @ 524

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

fix cif bug; add print traceback on some exceptions

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