source: trunk/GSASII.py @ 539

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

install OpenGL if not installed

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