source: trunk/GSASII.py @ 482

Last change on this file since 482 was 482, checked in by vondreele, 12 years ago

move FileDlgFixExt? to G2IO
begin to add a save selected seq results to file
move IO routines called in G2struct back there
remove wx stuff from G2pwd & G2struct
put progress bar in G2pwdGUI (not G2pwd)

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