source: trunk/GSASII.py @ 481

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

fix the up/down arrow behavior on the tree - used to skip

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