source: trunk/GSASII.py @ 570

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

Add checks on constraints: if problems display error window when displayed, added/edited & on Refine; handle GPX w/o doPawley flag

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