source: trunk/GSASII.py @ 473

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

Add FileDlgFixExt? to fix linux problem in FileDialog? where the extension is not taken from the wildcard choice.

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