source: trunk/GSASII.py @ 469

Last change on this file since 469 was 469, checked in by toby, 11 years ago

rework phase import

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