source: trunk/GSASII.py @ 567

Last change on this file since 567 was 567, checked in by toby, 12 years ago

more work on constraints

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