source: trunk/GSASII.py @ 540

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

revisions to teh opengl loader

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