source: trunk/GSASII.py @ 342

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

major modifications to get 1st "working" version of Refine
Add GSASIImapvars.py
fix cell refinement in indexing window
single cycle for peak refinement

  • Property svn:keywords set to Date Author Revision URL Id
File size: 66.9 KB
Line 
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3#GSASII
4########### SVN repository information ###################
5# $Date: 2011-08-05 19:35:43 +0000 (Fri, 05 Aug 2011) $
6# $Author: vondreele $
7# $Revision: 342 $
8# $URL: trunk/GSASII.py $
9# $Id: GSASII.py 342 2011-08-05 19:35:43Z vondreele $
10########### SVN repository information ###################
11
12import os
13import os.path as ospath
14import sys
15import math
16import cPickle
17import time
18import copy
19import numpy as np
20import scipy as sp
21import wx
22import matplotlib as mpl
23
24# load the GSAS routines
25import GSASIIpath
26import GSASIIIO as G2IO
27import GSASIIgrid as G2gd
28import GSASIIplot as G2plt
29import GSASIIpwdGUI as G2pdG
30import GSASIIspc as G2spc
31import GSASIIstruct as G2str
32import GSASIIsolve as G2sol
33import OpenGL as ogl
34
35# print versions
36print "Available python module versions for GSASII:"
37print "python:     ",sys.version[:5]
38print "wxpython:   ",wx.__version__
39print "matplotlib: ",mpl.__version__
40print "numpy:      ",np.__version__
41print "scipy:      ",sp.__version__
42print "OpenGL:     ",ogl.__version__
43try:
44    import mkl
45    print "Max threads ",mkl.get_max_threads()
46except:
47    print "MKL module not present"
48__version__ = '0.1.5'
49
50# useful degree trig functions
51sind = lambda x: math.sin(x*math.pi/180.)
52cosd = lambda x: math.cos(x*math.pi/180.)
53tand = lambda x: math.tan(x*math.pi/180.)
54asind = lambda x: 180.*math.asin(x)/math.pi
55acosd = lambda x: 180.*math.acos(x)/math.pi
56atan2d = lambda x,y: 180.*math.atan2(y,x)/math.pi
57
58def create(parent):
59    return GSASII(parent)
60
61[wxID_PATTERNTREE, 
62] = [wx.NewId() for _init_ctrls in range(1)]
63
64[wxID_FILECLOSE, wxID_FILEEXIT, wxID_FILEOPEN,  wxID_FILESAVE, wxID_FILESAVEAS, 
65wxID_REFINE, wxID_SOLVE, wxID_MAKEPDFS,
66] = [wx.NewId() for _init_coll_File_Items in range(8)]
67
68[wxID_PWDRREAD,wxID_SNGLREAD,wxID_ADDPHASE,wxID_DELETEPHASE,
69 wxID_DATADELETE,wxID_READPEAKS,wxID_PWDSUM,wxID_IMGREAD,
70 wxID_IMSUM, wxID_DATARENAME,
71] = [wx.NewId() for _init_coll_Data_Items in range(10)]
72
73[wxID_IMPORT, wxID_IMPORTPATTERN, wxID_IMPORTHKL, wxID_IMPORTPHASE,
74wxID_IMPORTCIF, wxID_IMPORTPDB, 
75] = [wx.NewId() for _init_coll_Import_Items in range(6)]
76
77[wxID_EXPORT, wxID_EXPORTPATTERN, wxID_EXPORTHKL, wxID_EXPORTPHASE,
78wxID_EXPORTCIF, wxID_EXPORTPEAKLIST, wxID_EXPORTPDF,
79] = [wx.NewId() for _init_coll_Export_Items in range(7)]
80
81[wxID_HELPABOUT, wxID_HELPHELP, 
82] = [wx.NewId() for _init_coll_Help_Items in range(2)]
83
84class GSASII(wx.Frame):
85   
86    def _init_coll_GSASIIMenu_Menus(self, parent):
87        parent.Append(menu=self.File, title='File')
88        parent.Append(menu=self.Data, title='Data')
89        parent.Append(menu=self.Calculate, title='Calculate')
90        parent.Append(menu=self.Import, title='Import')
91        parent.Append(menu=self.Export, title='Export')
92        parent.Append(menu=self.Help, title='Help')
93
94    def _init_coll_File_Items(self, parent):
95        parent.Append(help='Open a gsasii project file (*.gpx)', id=wxID_FILEOPEN,
96             kind=wx.ITEM_NORMAL,text='Open project...')
97        parent.Append(help='Save project to old file', id=wxID_FILESAVE, 
98            kind=wx.ITEM_NORMAL,text='Save project')
99        parent.Append(help='Save project to new file', id=wxID_FILESAVEAS, 
100            kind=wx.ITEM_NORMAL,text='Save As...')
101        parent.Append(help='Close project, saving is optional', id=wxID_FILECLOSE, 
102            kind=wx.ITEM_NORMAL,text='Close project')
103        parent.Append(help='Exit from gsasii', id=wxID_FILEEXIT, kind=wx.ITEM_NORMAL,
104            text='Exit')
105        self.Bind(wx.EVT_MENU, self.OnFileOpen, id=wxID_FILEOPEN)
106        self.Bind(wx.EVT_MENU, self.OnFileSave, id=wxID_FILESAVE)
107        self.Bind(wx.EVT_MENU, self.OnFileSaveas, id=wxID_FILESAVEAS)
108        self.Bind(wx.EVT_MENU, self.OnFileClose, id=wxID_FILECLOSE)
109        self.Bind(wx.EVT_MENU, self.OnFileExit, id=wxID_FILEEXIT)
110       
111    def _init_coll_Data_Items(self,parent):
112        parent.Append(help='', id=wxID_PWDRREAD, kind=wx.ITEM_NORMAL,
113            text='Read powder data...')
114        parent.Append(help='',id=wxID_IMGREAD, kind=wx.ITEM_NORMAL,
115            text='Read image data...')
116        parent.Append(help='',id=wxID_READPEAKS, kind=wx.ITEM_NORMAL,
117            text='Read Powder Pattern Peaks...')
118        parent.Append(help='', id=wxID_SNGLREAD, kind=wx.ITEM_NORMAL,
119            text='Read single crystal data...')
120        parent.Append(help='', id=wxID_PWDSUM, kind=wx.ITEM_NORMAL,
121            text='Sum powder data')
122        parent.Append(help='',id=wxID_IMSUM, kind=wx.ITEM_NORMAL,
123            text='Sum image data')
124        parent.Append(help='', id=wxID_ADDPHASE, kind=wx.ITEM_NORMAL,
125            text='Add phase')
126        parent.Append(help='', id=wxID_DELETEPHASE, kind=wx.ITEM_NORMAL,
127            text='Delete phase')
128        parent.Append(help='', id=wxID_DATARENAME, kind=wx.ITEM_NORMAL,
129            text='Rename data') 
130        parent.Append(help='', id=wxID_DATADELETE, kind=wx.ITEM_NORMAL,
131            text='Delete data')
132        self.Bind(wx.EVT_MENU, self.OnPwdrRead, id=wxID_PWDRREAD)
133        self.Bind(wx.EVT_MENU, self.OnPwdrSum, id=wxID_PWDSUM)
134        self.Bind(wx.EVT_MENU, self.OnReadPowderPeaks, id=wxID_READPEAKS)
135        self.Bind(wx.EVT_MENU, self.OnImageRead, id=wxID_IMGREAD)
136        self.Bind(wx.EVT_MENU, self.OnImageSum, id=wxID_IMSUM)
137        self.Bind(wx.EVT_MENU, self.OnSnglRead, id=wxID_SNGLREAD)
138        self.Bind(wx.EVT_MENU, self.OnAddPhase, id=wxID_ADDPHASE)
139        self.Bind(wx.EVT_MENU, self.OnDeletePhase, id=wxID_DELETEPHASE)
140        self.Bind(wx.EVT_MENU, self.OnRenameData, id=wxID_DATARENAME)
141        self.Bind(wx.EVT_MENU, self.OnDataDelete, id=wxID_DATADELETE)
142               
143    def _init_coll_Calculate_Items(self,parent):
144        self.MakePDF = parent.Append(help='Make new PDFs from selected powder patterns', 
145            id=wxID_MAKEPDFS, kind=wx.ITEM_NORMAL,text='Make new PDFs')
146        self.Bind(wx.EVT_MENU, self.OnMakePDFs, id=wxID_MAKEPDFS)
147        self.Refine = parent.Append(help='', id=wxID_REFINE, kind=wx.ITEM_NORMAL,
148            text='Refine')
149        self.Refine.Enable(True)
150        self.Bind(wx.EVT_MENU, self.OnRefine, id=wxID_REFINE)
151        self.Solve = parent.Append(help='', id=wxID_SOLVE, kind=wx.ITEM_NORMAL,
152            text='Solve')
153        self.Solve.Enable(False)
154        self.Bind(wx.EVT_MENU, self.OnSolve, id=wxID_SOLVE)
155       
156    def _init_coll_Import_Items(self,parent):
157        self.ImportPhase = parent.Append(help='Import phase data from GSAS EXP file',
158            id=wxID_IMPORTPHASE, kind=wx.ITEM_NORMAL,text='Import GSAS EXP Phase...')
159        self.ImportPDB = parent.Append(help='Import phase data from PDB file',
160            id=wxID_IMPORTPDB, kind=wx.ITEM_NORMAL,text='Import PDB Phase...')
161        self.ImportCIF = parent.Append(help='Import phase data from cif file',id=wxID_IMPORTCIF, kind=wx.ITEM_NORMAL,
162            text='Import CIF Phase...')
163        self.ImportPattern = parent.Append(help='',id=wxID_IMPORTPATTERN, kind=wx.ITEM_NORMAL,
164            text='Import Powder Pattern...')
165        self.ImportHKL = parent.Append(help='',id=wxID_IMPORTHKL, kind=wx.ITEM_NORMAL,
166            text='Import HKLs...')
167        self.Bind(wx.EVT_MENU, self.OnImportPhase, id=wxID_IMPORTPHASE)
168        self.Bind(wx.EVT_MENU, self.OnImportPDB, id=wxID_IMPORTPDB)
169        self.Bind(wx.EVT_MENU, self.OnImportCIF, id=wxID_IMPORTCIF)
170        self.Bind(wx.EVT_MENU, self.OnImportPattern, id=wxID_IMPORTPATTERN)
171        self.Bind(wx.EVT_MENU, self.OnImportHKL, id=wxID_IMPORTHKL)
172
173    def _init_coll_Export_Items(self,parent):
174        self.ExportPattern = parent.Append(help='Select PWDR item to enable',id=wxID_EXPORTPATTERN, kind=wx.ITEM_NORMAL,
175            text='Export Powder Patterns...')
176        self.ExportPeakList = parent.Append(help='',id=wxID_EXPORTPEAKLIST, kind=wx.ITEM_NORMAL,
177            text='Export All Peak Lists...')
178        self.ExportHKL = parent.Append(help='',id=wxID_EXPORTHKL, kind=wx.ITEM_NORMAL,
179            text='Export HKLs...')
180        self.ExportPDF = parent.Append(help='Select PDF item to enable',id=wxID_EXPORTPDF, kind=wx.ITEM_NORMAL,
181            text='Export PDF...')
182        self.ExportPhase = parent.Append(help='',id=wxID_EXPORTPHASE, kind=wx.ITEM_NORMAL,
183            text='Export Phase...')
184        self.ExportCIF = parent.Append(help='',id=wxID_EXPORTCIF, kind=wx.ITEM_NORMAL,
185            text='Export CIF...')
186        self.ExportPattern.Enable(False)
187        self.ExportPeakList.Enable(True)
188        self.ExportHKL.Enable(False)
189        self.ExportPDF.Enable(False)
190        self.ExportPhase.Enable(False)
191        self.ExportCIF.Enable(False)
192        self.Bind(wx.EVT_MENU, self.OnExportPatterns, id=wxID_EXPORTPATTERN)
193        self.Bind(wx.EVT_MENU, self.OnExportPeakList, id=wxID_EXPORTPEAKLIST)
194        self.Bind(wx.EVT_MENU, self.OnExportHKL, id=wxID_EXPORTHKL)
195        self.Bind(wx.EVT_MENU, self.OnExportPDF, id=wxID_EXPORTPDF)
196        self.Bind(wx.EVT_MENU, self.OnExportPhase, id=wxID_EXPORTPHASE)
197        self.Bind(wx.EVT_MENU, self.OnExportCIF, id=wxID_EXPORTCIF)
198               
199    def _init_coll_Help_Items(self, parent):
200        parent.Append(help='', id=wxID_HELPHELP, kind=wx.ITEM_NORMAL,
201            text='Help')
202        parent.Append(help='', id=wxID_HELPABOUT, kind=wx.ITEM_NORMAL,
203            text='About')
204        self.Bind(wx.EVT_MENU, self.OnHelpHelp, id=wxID_HELPHELP)
205        self.Bind(wx.EVT_MENU, self.OnHelpAbout, id=wxID_HELPABOUT)
206
207    def _init_utils(self):
208        self.GSASIIMenu = wx.MenuBar()
209        self.File = wx.Menu(title='')
210        self.Data = wx.Menu(title='')       
211        self.Calculate = wx.Menu(title='')       
212        self.Import = wx.Menu(title='')       
213        self.Export = wx.Menu(title='')       
214        self.Help = wx.Menu(title='')
215
216        self._init_coll_GSASIIMenu_Menus(self.GSASIIMenu)
217        self._init_coll_File_Items(self.File)
218        self._init_coll_Data_Items(self.Data)
219        self._init_coll_Calculate_Items(self.Calculate)
220        self._init_coll_Import_Items(self.Import)
221        self._init_coll_Export_Items(self.Export)
222        self._init_coll_Help_Items(self.Help)
223       
224    def _init_ctrls(self, parent):
225        wx.Frame.__init__(self, name='GSASII', parent=parent,
226            size=wx.Size(300, 250),style=wx.DEFAULT_FRAME_STYLE, title='GSAS-II data tree')
227        clientSize = wx.ClientDisplayRect()
228        Size = self.GetSize()
229        xPos = clientSize[2]-Size[0]
230        self.SetPosition(wx.Point(xPos,clientSize[1]))
231        self._init_utils()
232        self.SetMenuBar(self.GSASIIMenu)
233        self.Bind(wx.EVT_SIZE, self.OnSize)
234        self.CreateStatusBar()
235        self.mainPanel = wx.Panel(self,-1)
236       
237        self.PatternTree = wx.TreeCtrl(id=wxID_PATTERNTREE,
238            parent=self.mainPanel, pos=wx.Point(0, 0),style=wx.TR_DEFAULT_STYLE )
239        self.PatternTree.Bind(wx.EVT_TREE_SEL_CHANGED,
240            self.OnPatternTreeSelChanged, id=wxID_PATTERNTREE)
241        self.PatternTree.Bind(wx.EVT_TREE_ITEM_COLLAPSED,
242            self.OnPatternTreeItemCollapsed, id=wxID_PATTERNTREE)
243        self.PatternTree.Bind(wx.EVT_TREE_ITEM_EXPANDED,
244            self.OnPatternTreeItemExpanded, id=wxID_PATTERNTREE)
245        self.root = self.PatternTree.AddRoot('Loaded Data: ')
246       
247        plotFrame = wx.Frame(None,-1,'GSASII Plots',size=wx.Size(700,600), \
248            style=wx.DEFAULT_FRAME_STYLE ^ wx.CLOSE_BOX)
249        self.G2plotNB = G2plt.G2PlotNoteBook(plotFrame)
250        plotFrame.Show()
251       
252        self.dataDisplay = None
253       
254    def __init__(self, parent):
255        self._init_ctrls(parent)
256        self.Bind(wx.EVT_CLOSE, self.ExitMain)
257        # various defaults
258        self.GSASprojectfile = ''
259        self.dirname = ''
260        self.undofile = ''
261        self.Offset = [0.0,0.0]
262        self.Weight = False
263        self.IparmName = ''
264        self.IfPlot = False
265        self.PatternId = 0
266        self.PickId = 0
267        self.PeakTable = []
268        self.LimitsTable = []
269        self.HKL = []
270        self.Lines = []
271        self.itemPicked = None
272        self.dataFrame = None
273        self.Interpolate = 'nearest'
274        self.ContourColor = 'Paired'
275        self.Projection = 'equal area'
276        self.logPlot = False
277        self.qPlot = False
278        self.Contour = False
279        self.Legend = False
280        self.SinglePlot = False
281        self.plotView = 0
282        self.Image = 0
283        self.oldImagefile = ''
284        self.Integrate = 0
285        self.Pwdr = False
286        self.imageDefault = {}
287        self.Sngl = 0
288        self.ifGetRing = False
289        self.setPoly = False
290        arg = sys.argv
291        if len(arg) > 1:
292            self.GSASprojectfile = arg[1]
293            self.dirname = ospath.dirname(arg[1])
294            G2IO.ProjFileOpen(self)
295            self.PatternTree.Expand(self.root)
296            self.Refine.Enable(True)
297            self.Solve.Enable(True)
298
299    def OnSize(self,event):
300        w,h = self.GetClientSizeTuple()
301        self.mainPanel.SetSize(wx.Size(w,h))
302        self.PatternTree.SetSize(wx.Size(w,h))
303                       
304    def OnPatternTreeSelChanged(self, event):
305        pltNum = self.G2plotNB.nb.GetSelection()
306        if pltNum >= 0:                         #to avoid the startup with no plot!
307            pltPage = self.G2plotNB.nb.GetPage(pltNum)
308            pltPlot = pltPage.figure
309        item = event.GetItem()
310        G2gd.MovePatternTreeToGrid(self,item)
311       
312    def OnPatternTreeItemCollapsed(self, event):
313        event.Skip()
314
315    def OnPatternTreeItemExpanded(self, event):
316        event.Skip()
317       
318    def OnPatternTreeDeleteItem(self, event):
319        event.Skip()
320
321    def OnPatternTreeItemActivated(self, event):
322        event.Skip()
323       
324    def OnPwdrRead(self, event):
325        self.CheckNotebook()
326        dlg = wx.FileDialog(self, 'Choose files', '.', '', 
327            'GSAS fxye files (*.fxye)|*.fxye|GSAS fxy files (*.fxy)|*.fxy|Topas xye files (*.xye)|*.xye|All files (*.*)|*.*', 
328            wx.OPEN | wx.MULTIPLE)
329        if self.dirname: dlg.SetDirectory(self.dirname)
330        try:
331            if dlg.ShowModal() == wx.ID_OK:
332                filenames = dlg.GetPaths()
333                filenames.sort()
334                self.dirname = dlg.GetDirectory()
335                for filename in filenames:
336                    Data,Iparm,Comments,Temperature = G2IO.SelectPowderData(self, filename)              #Data: list of tuples (filename,Pos,Bank)
337                    if not Data:                                                    #if Data rejected by user - go to next one
338                        continue
339                    DataType = Iparm['INS   HTYPE ']                                #expect only 4 char string
340                    DataType = DataType.strip()[0:3]                                #just 1st 3 chars
341                    wx.BeginBusyCursor()
342                    Sample = {'Scale':[1.0,True],'Type':'Debye-Scherrer','Absorption':[0.0,False],
343                        'DisplaceX':[0.0,False],'DisplaceY':[0.0,False],'Diffuse':[],
344                        'Temperature':Temperature,'Pressure':1.0,'Humidity':0.0,'Voltage':0.0,
345                        'Force':0.0}
346                    try:
347                        for Item in Data:
348                            vals = Item[2].split()          #split up the BANK record
349                            Id = self.PatternTree.AppendItem(parent=self.root,text='PWDR '+ospath.basename(Item[0])+': '+vals[0]+vals[1])
350                            data = G2IO.GetPowderData(filename,Item[1],Item[2],DataType)
351                            self.PatternTree.SetItemPyData(Id,[Item,data])
352                            '''
353                            Each tree item data is a list with:
354                            Item: the (filename,Pos,Bank) tuple
355                            data: (x,y,w,yc,yb,yd) list  of np.arrays from GetPowderData
356                            '''
357                           
358                            self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Comments'),Comments)                           
359                            Tmin = min(data[0])
360                            Tmax = max(data[0])
361                            self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Limits'),[(Tmin,Tmax),[Tmin,Tmax]])
362                            self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Background'),[['chebyschev',1,3,1.0,0.0,0.0]])
363       
364                            data = [DataType,]
365                            if 'C' in DataType:
366                                s = Iparm['INS  1 ICONS']
367                                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
368                                if not v[1]:
369                                    names = ['Type','Lam','Zero','Polariz.','U','V','W','X','Y','SH/L','Azimuth'] 
370                                    v = (v[0],v[2],v[4])
371                                    codes = [0,0,0,0]
372                                else:
373                                    names = ['Type','Lam1','Lam2','Zero','I(L2)/I(L1)','Polariz.','U','V','W','X','Y','SH/L','Azimuth']
374                                    codes = [0,0,0,0,0,0]
375                                data.extend(v)
376                                v1 = Iparm['INS  1PRCF1 '].split()                                                 
377                                v = Iparm['INS  1PRCF11'].split()
378                                data.extend([float(v[0]),float(v[1]),float(v[2])])                  #get GU, GV & GW - always here
379                                try:
380                                    azm = float(Iparm['INS  1DETAZM'])
381                                except KeyError:                                                #not in this Iparm file
382                                    azm = 0.0
383                                v = Iparm['INS  1PRCF12'].split()
384                                if v1[0] == 3:
385                                    data.extend([float(v[0]),float(v[1]),float(v[2])+float(v[3],azm)])  #get LX, LY, S+H/L & azimuth
386                                else:
387                                    data.extend([0.0,0.0,0.002,azm])                                      #OK defaults if fxn #3 not 1st in iprm file
388                                codes.extend([0,0,0,0,0,0,0])
389                            self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Instrument Parameters'),[tuple(data),data,codes,names])
390                            self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Sample Parameters'),Sample)
391                            self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Peak List'),[])
392                            self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Index Peak List'),[])
393                            self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Unit Cells List'),[])
394                            self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Reflection Lists'),{})             
395                            self.PatternId = G2gd.GetPatternTreeItemId(self,Id,'Limits')
396                    finally:
397                        wx.EndBusyCursor()
398                self.PatternTree.Expand(Id)
399                self.PatternTree.SelectItem(Id)
400   
401        finally:
402            dlg.Destroy()
403       
404    def OnReadPowderPeaks(self,event):
405        Cuka = 1.54052
406        self.CheckNotebook()
407        dlg = wx.FileDialog(self, 'Choose file with peak list', '.', '', 
408            'peak files (*.txt)|*.txt|All files (*.*)|*.*',wx.OPEN)
409        if self.dirname:
410            dlg.SetDirectory(self.dirname)
411        try:
412            if dlg.ShowModal() == wx.ID_OK:
413                self.HKL = []
414                self.powderfile = dlg.GetPath()
415                self.dirname = dlg.GetDirectory()
416                comments,peaks = G2IO.GetPowderPeaks(self.powderfile)
417                Id = self.PatternTree.AppendItem(parent=self.root,text='PKS '+ospath.basename(self.powderfile))
418                data = ['PKS',Cuka,0.0]
419                names = ['Type','Lam','Zero'] 
420                codes = [0,0]
421                self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Instrument Parameters'),[tuple(data),data,codes,names])
422                self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Comments'),comments)
423                self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Index Peak List'),peaks)
424                self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Unit Cells List'),[])             
425                self.PatternTree.Expand(Id)
426                self.PatternTree.SelectItem(Id)
427        finally:
428            dlg.Destroy()
429           
430    def OnImageRead(self,event):
431        self.CheckNotebook()
432        dlg = wx.FileDialog(self, 'Choose image files', '.', '',\
433        'Any image file (*.tif;*.tiff;*.mar*;*.avg;*.sum;*.img;*.G2img)\
434        |*.tif;*.tiff;*.mar*;*.avg;*.sum;*.img;*.G2img|\
435        Any detector tif (*.tif;*.tiff)|*.tif;*.tiff|\
436        MAR file (*.mar*)|*.mar*|\
437        GE Image (*.avg;*.sum)|*.avg;*.sum|\
438        ADSC Image (*.img)|*.img|\
439        GSAS-II Image (*.G2img)|*.G2img|\
440        All files (*.*)|*.*',
441        wx.OPEN | wx.MULTIPLE)
442        if self.dirname:
443            dlg.SetDirectory(self.dirname)
444        try:
445            if dlg.ShowModal() == wx.ID_OK:
446                self.dirname = dlg.GetDirectory()
447                imagefiles = dlg.GetPaths()
448                imagefiles.sort()
449                for imagefile in imagefiles:
450                    Comments,Data,Npix,Image = G2IO.GetImageData(self,imagefile)
451                    if Comments:
452                        Id = self.PatternTree.AppendItem(parent=self.root,text='IMG '+ospath.basename(imagefile))
453                        self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Comments'),Comments)
454                        Imax = np.amax(Image)
455                        Imin = max(0.0,np.amin(Image))          #force positive
456                        if self.imageDefault:
457                            Data = copy.copy(self.imageDefault)
458                            Data['showLines'] = True
459                            Data['ring'] = []
460                            Data['rings'] = []
461                            Data['cutoff'] = 10
462                            Data['pixLimit'] = 20
463                            Data['edgemin'] = 100000000
464                            Data['calibdmin'] = 0.5
465                            Data['calibskip'] = 0
466                            Data['ellipses'] = []
467                            Data['calibrant'] = ''
468                        else:
469                            Data['type'] = 'PWDR'
470                            Data['color'] = 'binary'
471                            Data['tilt'] = 0.0
472                            Data['rotation'] = 0.0
473                            Data['showLines'] = False
474                            Data['ring'] = []
475                            Data['rings'] = []
476                            Data['cutoff'] = 10
477                            Data['pixLimit'] = 20
478                            Data['calibdmin'] = 0.5
479                            Data['calibskip'] = 0
480                            Data['edgemin'] = 100000000
481                            Data['ellipses'] = []
482                            Data['calibrant'] = ''
483                            Data['IOtth'] = [2.0,5.0]
484                            Data['LRazimuth'] = [-135,-45]
485                            Data['azmthOff'] = 0.0
486                            Data['outChannels'] = 2500
487                            Data['outAzimuths'] = 1
488                            Data['fullIntegrate'] = False
489                            Data['setRings'] = False
490                        Data['setDefault'] = False
491                        Data['range'] = [(Imin,Imax),[Imin,Imax]]
492                        self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Image Controls'),Data)
493                        Masks = {'Points':[],'Rings':[],'Arcs':[],'Polygons':[],'Thresholds':[(Imin,Imax),[Imin,Imax]]}
494                        self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Masks'),Masks)
495                        self.PatternTree.SetItemPyData(Id,[Npix,imagefile])
496                        self.PickId = Id
497                        self.Image = Id
498                self.PatternTree.SelectItem(G2gd.GetPatternTreeItemId(self,Id,'Image Controls'))             #show last one
499        finally:
500            dlg.Destroy()
501       
502    def OnSnglRead(self,event):
503        self.CheckNotebook()
504        dlg = wx.FileDialog(self, 'Choose file', '.', '', 
505            'hkl files (*.hkl)|*.hkl|All files (*.*)|*.*', 
506            wx.OPEN)
507        if self.dirname: dlg.SetDirectory(self.dirname)
508        try:
509            if dlg.ShowModal() == wx.ID_OK:
510                filename = dlg.GetPath()
511                self.dirname = dlg.GetDirectory()
512                wx.BeginBusyCursor()
513                try:
514                    Data = {}
515                    names = ['Type','Lam']
516                    HKLref,HKLmin,HKLmax,FoMax,ifFc = G2IO.GetHKLData(filename)
517                    Id = self.PatternTree.AppendItem(parent=self.root,text='HKLF '+ospath.basename(filename))
518                    self.PatternTree.SetItemPyData(Id,HKLref)
519                    Sub = self.PatternTree.AppendItem(Id,text='Instrument Parameters')
520                    data = ['SXC',1.5428,]
521                    self.PatternTree.SetItemPyData(Sub,[tuple(data),data,names])
522                    Data['Type'] = 'Fosq'
523                    Data['ifFc'] = ifFc
524                    Data['HKLmax'] = HKLmax
525                    Data['HKLmin'] = HKLmin
526                    Data['FoMax'] = FoMax
527                    Data['Zone'] = '001'
528                    Data['Layer'] = 0
529                    Data['Scale'] = 1.0
530                    Data['log-lin'] = 'lin'                   
531                    self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='HKL Plot Controls'),Data)
532                    self.PatternTree.SelectItem(Id)
533                    self.PatternTree.Expand(Id)
534                    self.Sngl = Id
535                finally:
536                    wx.EndBusyCursor()   
537        finally:
538            dlg.Destroy()
539           
540    def CheckNotebook(self):
541        if not G2gd.GetPatternTreeItemId(self,self.root,'Notebook'):
542            sub = self.PatternTree.AppendItem(parent=self.root,text='Notebook')
543            self.PatternTree.SetItemPyData(sub,[''])
544            sub = self.PatternTree.AppendItem(parent=self.root,text='Controls')
545            self.PatternTree.SetItemPyData(sub,{})
546               
547    class CopyDialog(wx.Dialog):
548        def __init__(self,parent,title,text,data):
549            wx.Dialog.__init__(self,parent,-1,title, 
550                pos=wx.DefaultPosition,style=wx.DEFAULT_DIALOG_STYLE)
551            self.data = data
552            panel = wx.Panel(self)
553            mainSizer = wx.BoxSizer(wx.VERTICAL)
554            topLabl = wx.StaticText(panel,-1,text)
555            mainSizer.Add((10,10),1)
556            mainSizer.Add(topLabl,0,wx.ALIGN_CENTER_VERTICAL|wx.LEFT,10)
557            mainSizer.Add((10,10),1)
558            ncols = len(data)/40+1
559            dataGridSizer = wx.FlexGridSizer(rows=len(data),cols=ncols,hgap=2,vgap=2)
560            for id,item in enumerate(self.data):
561                ckbox = wx.CheckBox(panel,id,item[1])
562                ckbox.Bind(wx.EVT_CHECKBOX,self.OnCopyChange)                   
563                dataGridSizer.Add(ckbox,0,wx.LEFT,10)
564            mainSizer.Add(dataGridSizer,0,wx.EXPAND)
565            OkBtn = wx.Button(panel,-1,"Ok")
566            OkBtn.Bind(wx.EVT_BUTTON, self.OnOk)
567            cancelBtn = wx.Button(panel,-1,"Cancel")
568            cancelBtn.Bind(wx.EVT_BUTTON, self.OnCancel)
569            btnSizer = wx.BoxSizer(wx.HORIZONTAL)
570            btnSizer.Add((20,20),1)
571            btnSizer.Add(OkBtn)
572            btnSizer.Add((20,20),1)
573            btnSizer.Add(cancelBtn)
574            btnSizer.Add((20,20),1)
575           
576            mainSizer.Add(btnSizer,0,wx.EXPAND|wx.BOTTOM|wx.TOP, 10)
577            panel.SetSizer(mainSizer)
578            panel.Fit()
579            self.Fit()
580       
581        def OnCopyChange(self,event):
582            id = event.GetId()
583            self.data[id][0] = self.FindWindowById(id).GetValue()       
584           
585        def OnOk(self,event):
586            parent = self.GetParent()
587            parent.Raise()
588            self.EndModal(wx.ID_OK)             
589            self.Destroy()
590           
591        def OnCancel(self,event):
592            parent = self.GetParent()
593            parent.Raise()
594            self.EndModal(wx.ID_CANCEL)             
595            self.Destroy()
596           
597        def GetData(self):
598            return self.data
599       
600    class SumDialog(wx.Dialog):
601        def __init__(self,parent,title,text,dataType,data):
602            wx.Dialog.__init__(self,parent,-1,title, 
603                pos=wx.DefaultPosition,style=wx.DEFAULT_DIALOG_STYLE)
604            self.data = data
605            panel = wx.Panel(self)
606            mainSizer = wx.BoxSizer(wx.VERTICAL)
607            topLabl = wx.StaticText(panel,-1,text)
608            mainSizer.Add((10,10),1)
609            mainSizer.Add(topLabl,0,wx.ALIGN_CENTER_VERTICAL|wx.LEFT,10)
610            mainSizer.Add((10,10),1)
611            dataGridSizer = wx.FlexGridSizer(rows=len(data),cols=2,hgap=2,vgap=2)
612            for id,item in enumerate(self.data[:-1]):
613                name = wx.TextCtrl(panel,-1,item[1],size=wx.Size(200,20))
614                name.SetEditable(False)
615                scale = wx.TextCtrl(panel,id,str(item[0]),style=wx.TE_PROCESS_ENTER)
616                scale.Bind(wx.EVT_TEXT_ENTER,self.OnScaleChange)
617                scale.Bind(wx.EVT_KILL_FOCUS,self.OnScaleChange)
618                dataGridSizer.Add(scale,0,wx.LEFT,10)
619                dataGridSizer.Add(name,0,wx.RIGHT,10)
620            dataGridSizer.Add(wx.StaticText(panel,-1,'Sum result name: '+dataType),0, \
621                wx.LEFT|wx.TOP|wx.ALIGN_CENTER_VERTICAL,10)
622            self.name = wx.TextCtrl(panel,-1,self.data[-1],size=wx.Size(200,20),style=wx.TE_PROCESS_ENTER)
623            self.name.Bind(wx.EVT_TEXT_ENTER,self.OnNameChange)
624            self.name.Bind(wx.EVT_KILL_FOCUS,self.OnNameChange)
625            dataGridSizer.Add(self.name,0,wx.RIGHT|wx.TOP,10)
626            mainSizer.Add(dataGridSizer,0,wx.EXPAND)
627            OkBtn = wx.Button(panel,-1,"Ok")
628            OkBtn.Bind(wx.EVT_BUTTON, self.OnOk)
629            cancelBtn = wx.Button(panel,-1,"Cancel")
630            cancelBtn.Bind(wx.EVT_BUTTON, self.OnCancel)
631            btnSizer = wx.BoxSizer(wx.HORIZONTAL)
632            btnSizer.Add((20,20),1)
633            btnSizer.Add(OkBtn)
634            btnSizer.Add((20,20),1)
635            btnSizer.Add(cancelBtn)
636            btnSizer.Add((20,20),1)
637           
638            mainSizer.Add(btnSizer,0,wx.EXPAND|wx.BOTTOM|wx.TOP, 10)
639            panel.SetSizer(mainSizer)
640            panel.Fit()
641            self.Fit()
642           
643        def OnNameChange(self,event):
644            self.data[-1] = self.name.GetValue() 
645           
646        def OnScaleChange(self,event):
647            id = event.GetId()
648            value = self.FindWindowById(id).GetValue()
649            try:
650                self.data[id][0] = float(value)
651                self.FindWindowById(id).SetValue('%.3f'%(self.data[id][0]))
652            except ValueError:
653                if value and '-' not in value[0]:
654                    print 'bad input - numbers only'
655                    self.FindWindowById(id).SetValue('0.0')
656           
657        def OnOk(self,event):
658            parent = self.GetParent()
659            parent.Raise()
660            self.EndModal(wx.ID_OK)             
661            self.Destroy()
662           
663        def OnCancel(self,event):
664            parent = self.GetParent()
665            parent.Raise()
666            self.EndModal(wx.ID_CANCEL)             
667            self.Destroy()
668           
669        def GetData(self):
670            return self.data
671           
672    def OnPwdrSum(self,event):
673        TextList = []
674        DataList = []
675        SumList = []
676        Names = []
677        Inst = []
678        SumItemList = []
679        Comments = ['Sum equals: \n']
680        if self.PatternTree.GetCount():
681            item, cookie = self.PatternTree.GetFirstChild(self.root)
682            while item:
683                name = self.PatternTree.GetItemText(item)
684                Names.append(name)
685                if 'PWDR' in name:
686                    TextList.append([0.0,name])
687                    DataList.append(self.PatternTree.GetItemPyData(item)[1])    # (x,y,w,yc,yb,yd)
688                    if not Inst:
689                        Inst = self.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(self,item, 'Instrument Parameters'))
690                item, cookie = self.PatternTree.GetNextChild(self.root, cookie)
691            if len(TextList) < 2:
692                self.ErrorDialog('Not enough data to sum','There must be more than one "PWDR" pattern')
693                return
694            TextList.append('default_sum_name')               
695            dlg = self.SumDialog(self,'Sum data','Enter scale for each pattern in summation','PWDR',TextList)
696            try:
697                if dlg.ShowModal() == wx.ID_OK:
698                    lenX = 0
699                    Xminmax = [0,0]
700                    Xsum = []
701                    Ysum = []
702                    Vsum = []
703                    result = dlg.GetData()
704                    for i,item in enumerate(result[:-1]):
705                        scale,name = item
706                        data = DataList[i]
707                        if scale:
708                            Comments.append("%10.3f %s" % (scale,' * '+name))
709                            x,y,w,yc,yb,yd = data
710                            v = 1./w
711                            if lenX:
712                                if lenX != len(x):
713                                    self.ErrorDialog('Data length error','Data to be summed must have same number of points'+ \
714                                        '\nExpected:'+str(lenX)+ \
715                                        '\nFound:   '+str(len(x))+'\nfor '+name)
716                                    return
717                            else:
718                                lenX = len(x)
719                            if Xminmax[1]:
720                                if Xminmax != [x[0],x[-1]]:
721                                    self.ErrorDialog('Data range error','Data to be summed must span same range'+ \
722                                        '\nExpected:'+str(Xminmax[0])+' '+str(Xminmax[1])+ \
723                                        '\nFound:   '+str(x[0])+' '+str(x[-1])+'\nfor '+name)
724                                    return
725                                else:
726                                    for j,yi in enumerate(y):
727                                         Ysum[j] += scale*yi
728                                         Vsum[j] += abs(scale)*v[j]
729                            else:
730                                Xminmax = [x[0],x[-1]]
731                                YCsum = YBsum = YDsum = [0.0 for i in range(lenX)]
732                                for j,yi in enumerate(y):
733                                    Xsum.append(x[j])
734                                    Ysum.append(scale*yi)
735                                    Vsum.append(abs(scale*v[j]))
736                    Wsum = 1./np.array(Vsum)
737                    outname = 'PWDR '+result[-1]
738                    Id = 0
739                    if outname in Names:
740                        dlg2 = wx.MessageDialog(self,'Overwrite data?','Duplicate data name',wx.OK|wx.CANCEL)
741                        try:
742                            if dlg2.ShowModal() == wx.ID_OK:
743                                Id = G2gd.GetPatternTreeItemId(self,self.root,name)
744                                self.PatternTree.Delete(Id)
745                        finally:
746                            dlg2.Destroy()
747                    Id = self.PatternTree.AppendItem(parent=self.root,text=outname)
748                    if Id:
749                        Sample = {'Scale':[1.0,True],'Type':'Debye-Scherrer','Absorption':[0.0,False],
750                            'DisplaceX':[0.0,False],'DisplaceY':[0.0,False],'Diffuse':[],
751                            'Temperature':300.,'Pressure':1.0,'Humidity':0.0,
752                            'Voltage':0.0,'Force':0.0,'Gonio. radius':200.0}
753                        self.PatternTree.SetItemPyData(Id,[[''],[Xsum,Ysum,Wsum,YCsum,YBsum,YDsum]])
754                        self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Comments'),Comments)                   
755                        self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Limits'),[tuple(Xminmax),Xminmax])
756                        self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Background'),[['chebyschev',1,3,1.0,0.0,0.0]])
757                        self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Instrument Parameters'),Inst)
758                        self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Sample Parameters'),Sample)
759                        self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Peak List'),[])
760                        self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Index Peak List'),[])
761                        self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Unit Cells List'),[])             
762                        self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Reflection Lists'),{})             
763                        self.PatternTree.SelectItem(Id)
764                        self.PatternTree.Expand(Id)
765                   
766            finally:
767                dlg.Destroy()
768
769    def OnImageSum(self,event):
770        TextList = []
771        DataList = []
772        SumList = []
773        Names = []
774        Inst = []
775        SumItemList = []
776        Comments = ['Sum equals: \n']
777        if self.PatternTree.GetCount():
778            item, cookie = self.PatternTree.GetFirstChild(self.root)
779            while item:
780                name = self.PatternTree.GetItemText(item)
781                Names.append(name)
782                if 'IMG' in name:
783                    TextList.append([0.0,name])
784                    DataList.append(self.PatternTree.GetItemPyData(item))        #Size,Image
785                    Data = self.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(self,item,'Image Controls'))
786                item, cookie = self.PatternTree.GetNextChild(self.root, cookie)
787            if len(TextList) < 2:
788                self.ErrorDialog('Not enough data to sum','There must be more than one "IMG" pattern')
789                return
790            TextList.append('default_sum_name')               
791            dlg = self.SumDialog(self,'Sum data','Enter scale for each image in summation','IMG',TextList)
792            try:
793                if dlg.ShowModal() == wx.ID_OK:
794                    imSize = 0
795                    result = dlg.GetData()
796                    First = True
797                    Found = False
798                    for i,item in enumerate(result[:-1]):
799                        scale,name = item
800                        data = DataList[i]
801                        if scale:
802                            Found = True                               
803                            Comments.append("%10.3f %s" % (scale,' * '+name))
804                            Npix,imagefile = data
805                            image = G2IO.GetImageData(self,imagefile,imageOnly=True)
806                            if First:
807                                newImage = np.zeros_like(image)
808                                First = False
809                            if imSize:
810                                if imSize != Npix:
811                                    self.ErrorDialog('Image size error','Images to be summed must be same size'+ \
812                                        '\nExpected:'+str(imSize)+ \
813                                        '\nFound:   '+str(Npix)+'\nfor '+name)
814                                    return
815                                newImage = newImage+scale*image
816                            else:
817                                imSize = Npix
818                                newImage = newImage+scale*image
819                            del(image)
820                    if not Found:
821                        self.ErrorDialog('Image sum error','No nonzero image multipliers found')
822                        return
823                       
824                    newImage = np.asfarray(newImage,dtype=np.float32)                       
825                    outname = 'IMG '+result[-1]
826                    Id = 0
827                    if outname in Names:
828                        dlg2 = wx.MessageDialog(self,'Overwrite data?','Duplicate data name',wx.OK|wx.CANCEL)
829                        try:
830                            if dlg2.ShowModal() == wx.ID_OK:
831                                Id = G2gd.GetPatternTreeItemId(self,self.root,name)
832                        finally:
833                            dlg2.Destroy()
834                    else:
835                        Id = self.PatternTree.AppendItem(parent=self.root,text=outname)
836                    if Id:
837                        dlg = wx.FileDialog(self, 'Choose sum image filename', '.', '', 
838                            'G2img files (*.G2img)|*.G2img', 
839                            wx.SAVE|wx.FD_OVERWRITE_PROMPT)
840                        if self.dirname: dlg.SetDirectory(self.dirname)
841                        if dlg.ShowModal() == wx.ID_OK:
842                            self.dirname = dlg.GetDirectory()
843                            newimagefile = dlg.GetPath()
844                            G2IO.PutG2Image(newimagefile,Comments,Data,Npix,newImage)
845                            Imax = np.amax(newImage)
846                            Imin = np.amin(newImage)
847                            newImage = []
848                            self.PatternTree.SetItemPyData(Id,[imSize,newimagefile])
849                            self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Comments'),Comments)
850                        del(newImage)
851                        if self.imageDefault:
852                            Data = copy.copy(self.imageDefault)
853                        Data['showLines'] = True
854                        Data['ring'] = []
855                        Data['rings'] = []
856                        Data['cutoff'] = 10
857                        Data['pixLimit'] = 20
858                        Data['ellipses'] = []
859                        Data['calibrant'] = ''
860                        Data['range'] = [(Imin,Imax),[Imin,Imax]]
861                        self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Image Controls'),Data)                                           
862                        Masks = {'Points':[],'Rings':[],'Arcs':[],'Polygons':[],'Thresholds':[(Imin,Imax),[Imin,Imax]]}
863                        self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='Masks'),Masks)
864                        self.PatternTree.SelectItem(Id)
865                        self.PatternTree.Expand(Id)
866                        self.PickId = G2gd.GetPatternTreeItemId(self,self.root,outname)
867                        self.Image = self.PickId
868            finally:
869                dlg.Destroy()
870                     
871    def OnAddPhase(self,event):
872        if not G2gd.GetPatternTreeItemId(self,self.root,'Phases'):
873            sub = self.PatternTree.AppendItem(parent=self.root,text='Phases')
874        else:
875            sub = G2gd.GetPatternTreeItemId(self,self.root,'Phases')
876        PhaseName = ''
877        dlg = wx.TextEntryDialog(None,'Enter a name for this phase','Phase Name Entry','New phase',
878            style=wx.OK)
879        if dlg.ShowModal() == wx.ID_OK:
880            PhaseName = dlg.GetValue()
881        dlg.Destroy()
882        sub = self.PatternTree.AppendItem(parent=sub,text=PhaseName)
883        E,SGData = G2spc.SpcGroup('P 1')
884        self.PatternTree.SetItemPyData(sub, {
885            'General':{
886                'Name':PhaseName,
887                'Type':'nuclear',
888                'SGData':SGData,
889                'Cell':[False,10.,10.,10.,90.,90.,90,1000.],
890                'Pawley dmin':1.0},
891            'Atoms':[],
892            'Drawing':{},
893            'Histograms':{},
894            'Pawley ref':[],
895            'Models':{},
896            'SH Texture':{
897                'Order':0,
898                'Model':'cylindrical',
899                'Sample omega':[False,0.0],
900                'Sample chi':[False,0.0],
901                'Sample phi':[False,0.0],
902                'SH Coeff':[False,{}],
903                'SHShow':False,
904                'PFhkl':[0,0,1],
905                'PFxyz':[0,0,1],
906                'PlotType':'Pole figure'}
907            })
908       
909    def OnDeletePhase(self,event):
910        #Hmm, also need to delete this phase from Reflection Lists for each PWDR histogram
911        if self.dataFrame:
912            self.dataFrame.Clear() 
913        TextList = []
914        DelList = []
915        DelItemList = []
916        if G2gd.GetPatternTreeItemId(self,self.root,'Phases'):
917            sub = G2gd.GetPatternTreeItemId(self,self.root,'Phases')
918        else:
919            return
920        if sub:
921            item, cookie = self.PatternTree.GetFirstChild(sub)
922            while item:
923                TextList.append(self.PatternTree.GetItemText(item))
924                item, cookie = self.PatternTree.GetNextChild(sub, cookie)               
925            dlg = wx.MultiChoiceDialog(self, 'Which phase to delete?', 'Delete phase', TextList, wx.CHOICEDLG_STYLE)
926            try:
927                if dlg.ShowModal() == wx.ID_OK:
928                    result = dlg.GetSelections()
929                    for i in result: DelList.append([i,TextList[i]])
930                    item, cookie = self.PatternTree.GetFirstChild(sub)
931                    i = 0
932                    while item:
933                        if [i,self.PatternTree.GetItemText(item)] in DelList: DelItemList.append(item)
934                        item, cookie = self.PatternTree.GetNextChild(sub, cookie)
935                        i += 1
936                    for item in DelItemList:
937                        name = self.PatternTree.GetItemText(item)
938                        self.PatternTree.Delete(item)
939                        self.G2plotNB.Delete(name)
940            finally:
941                dlg.Destroy()
942               
943    def OnRenameData(self,event):
944        name = self.PatternTree.GetItemText(self.PickId)     
945        if 'PWDR' in name or 'HKLF' in name or 'IMG' in name:
946            dataType = name[:name.index(' ')+1]                 #includes the ' '
947            dlg = wx.TextEntryDialog(self,'Data name: '+dataType,'Change data name',
948                defaultValue=name[name.index(' ')+1:])
949            try:
950                if dlg.ShowModal() == wx.ID_OK:
951                    self.PatternTree.SetItemText(self.PickId,dataType+dlg.GetValue())
952            finally:
953                dlg.Destroy()
954       
955    def GetFileList(self,fileType,skip=None):        #potentially useful?
956        fileList = []
957        Source = ''
958        id, cookie = self.PatternTree.GetFirstChild(self.root)
959        while id:
960            name = self.PatternTree.GetItemText(id)
961            if fileType in name:
962                if id == skip:
963                    Source = name
964                else:
965                    fileList.append([False,name,id])
966            id, cookie = self.PatternTree.GetNextChild(self.root, cookie)
967        if skip:
968            return fileList,Source
969        else:
970            return fileList
971           
972    def OnDataDelete(self, event):
973        TextList = ['All Data']
974        DelList = []
975        DelItemList = []
976        ifPWDR = False
977        ifIMG = False
978        ifHKLF = False
979        ifPDF = False
980        if self.PatternTree.GetCount():
981            item, cookie = self.PatternTree.GetFirstChild(self.root)
982            while item:
983                name = self.PatternTree.GetItemText(item)
984                if 'PWDR' in name or 'HKLF' in name or 'IMG' or 'PDF' in name:
985                    if 'PWDR' in name: ifPWDR = True
986                    if 'IMG' in name: ifIMG = True
987                    if 'HKLF' in name: ifHKLF = True
988                    if 'PDF' in name: ifPDF = True
989                    TextList.append(name)
990                item, cookie = self.PatternTree.GetNextChild(self.root, cookie)
991            if ifPWDR: TextList.insert(1,'All PWDR')
992            if ifIMG: TextList.insert(1,'All IMG')
993            if ifHKLF: TextList.insert(1,'All HKLF')
994            if ifPDF: TextList.insert(1,'All PDF')               
995            dlg = wx.MultiChoiceDialog(self, 'Which data to delete?', 'Delete data', TextList, wx.CHOICEDLG_STYLE)
996            try:
997                if dlg.ShowModal() == wx.ID_OK:
998                    result = dlg.GetSelections()
999                    for i in result: DelList.append(TextList[i])
1000                    if 'All Data' in DelList:
1001                        DelList = [item for item in TextList if item[:3] != 'All']
1002                    elif 'All PWDR' in DelList:
1003                        DelList = [item for item in TextList if item[:4] == 'PWDR']
1004                    elif 'All IMG' in DelList:
1005                        DelList = [item for item in TextList if item[:3] == 'IMG']
1006                    elif 'All HKLF' in DelList:
1007                        DelList = [item for item in TextList if item[:4] == 'HKLF']
1008                    elif 'All PDF' in DelList:
1009                        DelList = [item for item in TextList if item[:3] == 'PDF']
1010                    item, cookie = self.PatternTree.GetFirstChild(self.root)
1011                    while item:
1012                        if self.PatternTree.GetItemText(item) in DelList: DelItemList.append(item)
1013                        item, cookie = self.PatternTree.GetNextChild(self.root, cookie)
1014                    for item in DelItemList:
1015                        self.PatternTree.Delete(item)
1016                    G2plt.PlotPatterns(self,True)                        #so plot gets updated
1017            finally:
1018                dlg.Destroy()
1019
1020    def OnFileOpen(self, event):
1021        result = ''
1022        Id = 0
1023        if self.PatternTree.GetChildrenCount(self.root,False):
1024            if self.dataFrame:
1025                self.dataFrame.Clear() 
1026            dlg = wx.MessageDialog(self, 'Overwrite?','Project exists!',  wx.OK | wx.CANCEL)
1027            try:
1028                result = dlg.ShowModal()
1029                if result == wx.ID_OK:
1030                    self.PatternTree.DeleteChildren(self.root)
1031                    self.GSASprojectfile = ''
1032                    self.PatternTree.DeleteChildren(self.root)
1033                    if self.HKL: self.HKL = []
1034                    if self.G2plotNB.plotList:
1035                        self.G2plotNB.clear()
1036            finally:
1037                dlg.Destroy()
1038        if result != wx.ID_CANCEL:   
1039            if self.dataDisplay: self.dataDisplay.Destroy()
1040            dlg = wx.FileDialog(self, 'Choose GSAS-II project file', '.', '', 
1041                'GSAS-II project file (*.gpx)|*.gpx',wx.OPEN)
1042            if self.dirname: dlg.SetDirectory(self.dirname)
1043            try:
1044                if dlg.ShowModal() == wx.ID_OK:
1045                    self.GSASprojectfile = dlg.GetPath()
1046                    self.dirname = dlg.GetDirectory()
1047                    G2IO.ProjFileOpen(self)
1048                    self.PatternTree.SetItemText(self.root,'Loaded Data: '+self.GSASprojectfile)
1049                    self.PatternTree.Expand(self.root)
1050                    self.HKL = []
1051                    item, cookie = self.PatternTree.GetFirstChild(self.root)
1052                    while item and not Id:
1053                        name = self.PatternTree.GetItemText(item)
1054                        if name[:4] in ['PWDR','HKLF','IMG ','PDF ']:
1055                            Id = item
1056                        elif name == 'Controls':
1057                            data = self.PatternTree.GetItemPyData(item)
1058                            if data != [0] and data != {}:
1059                                self.Refine.Enable(True)
1060                                self.Solve.Enable(True)         #not right but something needed here
1061                        item, cookie = self.PatternTree.GetNextChild(self.root, cookie)               
1062                    if Id:
1063                        self.PatternTree.SelectItem(Id)
1064            finally:
1065                dlg.Destroy()
1066
1067    def OnFileClose(self, event):
1068        if self.dataFrame:
1069            self.dataFrame.Clear()
1070            self.dataFrame.SetLabel('GSAS-II data display') 
1071        dlg = wx.MessageDialog(self, 'Save current project?', ' ', wx.YES | wx.NO | wx.CANCEL)
1072        try:
1073            result = dlg.ShowModal()
1074            if result == wx.ID_OK:
1075                self.OnFileSaveMenu(event)
1076            if result != wx.ID_CANCEL:
1077                self.GSASprojectfile = ''
1078                self.PatternTree.SetItemText(self.root,'Loaded Data: ')
1079                self.PatternTree.DeleteChildren(self.root)
1080                if self.HKL: self.HKL = []
1081                if self.G2plotNB.plotList:
1082                    self.G2plotNB.clear()
1083        finally:
1084            dlg.Destroy()
1085
1086    def OnFileSave(self, event):
1087        if self.GSASprojectfile: 
1088            self.PatternTree.SetItemText(self.root,'Loaded Data: '+self.GSASprojectfile)
1089            G2IO.ProjFileSave(self)
1090        else:
1091            self.OnFileSaveas(event)
1092
1093    def OnFileSaveas(self, event):
1094        dlg = wx.FileDialog(self, 'Choose GSAS-II project file name', '.', '', 
1095            'GSAS-II project file (*.gpx)|*.gpx',wx.FD_SAVE|wx.FD_OVERWRITE_PROMPT)
1096        if self.dirname:
1097            dlg.SetDirectory(self.dirname)
1098        try:
1099            if dlg.ShowModal() == wx.ID_OK:
1100                self.GSASprojectfile = dlg.GetPath()
1101                self.PatternTree.SetItemText(self.root,'Loaded Data: '+self.GSASprojectfile)
1102                G2IO.ProjFileSave(self)
1103                self.dirname = dlg.GetDirectory()
1104        finally:
1105            dlg.Destroy()
1106
1107    def ExitMain(self, event):
1108        if self.undofile:
1109            os.remove(self.undofile)
1110        sys.exit()
1111       
1112    def OnFileExit(self, event):
1113        if self.dataFrame:
1114            self.dataFrame.Clear() 
1115            self.dataFrame.Destroy()
1116        self.Close()
1117       
1118    def OnImportPattern(self,event):
1119        dlg = wx.FileDialog(self, 'Choose nonGSAS powder file', '.', '', 
1120            '(*.*)|*.*',wx.OPEN)
1121        if self.dirname:
1122            dlg.SetDirectory(self.dirname)
1123        try:
1124            if dlg.ShowModal() == wx.ID_OK:
1125                self.powderfile = dlg.GetPath()
1126                self.dirname = dlg.GetDirectory()
1127        finally:
1128            dlg.Destroy()
1129           
1130    def OnImportHKL(self,event):
1131        dlg = wx.FileDialog(self, 'Choose structure factor file', '.', '', 
1132            '(*.*)|*.*',wx.OPEN)
1133        if self.dirname:
1134            dlg.SetDirectory(self.dirname)
1135        try:
1136            if dlg.ShowModal() == wx.ID_OK:
1137                self.HKLfile = dlg.GetPath()
1138                self.dirname = dlg.GetDirectory()
1139        finally:
1140            dlg.Destroy()
1141       
1142    def OnImportPhase(self,event):
1143        dlg = wx.FileDialog(self, 'Choose GSAS EXP file', '.', '', 
1144            'EXP file (*.EXP)|*.EXP',wx.OPEN)
1145        if self.dirname:
1146            dlg.SetDirectory(self.dirname)
1147        try:
1148            Phase = {}
1149            if dlg.ShowModal() == wx.ID_OK:
1150                EXPfile = dlg.GetPath()
1151                self.dirname = dlg.GetDirectory()
1152                Phase = G2IO.ReadEXPPhase(self,EXPfile)
1153        finally:
1154            dlg.Destroy()
1155        if Phase:
1156            PhaseName = Phase['General']['Name']
1157            if not G2gd.GetPatternTreeItemId(self,self.root,'Phases'):
1158                sub = self.PatternTree.AppendItem(parent=self.root,text='Phases')
1159            else:
1160                sub = G2gd.GetPatternTreeItemId(self,self.root,'Phases')
1161            sub = self.PatternTree.AppendItem(parent=sub,text=PhaseName)
1162            self.PatternTree.SetItemPyData(sub,Phase)
1163           
1164    def OnImportPDB(self,event):
1165        dlg = wx.FileDialog(self, 'Choose PDB file', '.', '', 
1166            'PDB file (*.pdb,*.ent)|*.pdb;*.ent|All files (*.*)|*.*',wx.OPEN)
1167        if self.dirname:
1168            dlg.SetDirectory(self.dirname)
1169        try:
1170            if dlg.ShowModal() == wx.ID_OK:
1171                PDBfile = dlg.GetPath()
1172                self.dirname = dlg.GetDirectory()
1173                Phase = G2IO.ReadPDBPhase(PDBfile)
1174        finally:
1175            dlg.Destroy()
1176        if Phase:
1177            PhaseName = Phase['General']['Name']
1178            if not G2gd.GetPatternTreeItemId(self,self.root,'Phases'):
1179                sub = self.PatternTree.AppendItem(parent=self.root,text='Phases')
1180            else:
1181                sub = G2gd.GetPatternTreeItemId(self,self.root,'Phases')
1182            sub = self.PatternTree.AppendItem(parent=sub,text=PhaseName)
1183            self.PatternTree.SetItemPyData(sub,Phase)       
1184       
1185    def OnImportCIF(self,event):
1186        dlg = wx.FileDialog(self, 'Choose CIF file', '.', '', 
1187            'CIF file (*.cif)|*.cif',wx.OPEN)
1188        if self.dirname:
1189            dlg.SetDirectory(self.dirname)
1190        try:
1191            if dlg.ShowModal() == wx.ID_OK:
1192                CIFfile = dlg.GetPath()
1193                self.dirname = dlg.GetDirectory()
1194                Phase = G2IO.ReadCIFPhase(CIFfile)
1195        finally:
1196            dlg.Destroy()
1197        if Phase:
1198            PhaseName = Phase['General']['Name']
1199            if not G2gd.GetPatternTreeItemId(self,self.root,'Phases'):
1200                sub = self.PatternTree.AppendItem(parent=self.root,text='Phases')
1201            else:
1202                sub = G2gd.GetPatternTreeItemId(self,self.root,'Phases')
1203            sub = self.PatternTree.AppendItem(parent=sub,text=PhaseName)
1204            self.PatternTree.SetItemPyData(sub,Phase)       
1205       
1206    def OnExportPatterns(self,event):
1207        names = ['All']
1208        exports = []
1209        item, cookie = self.PatternTree.GetFirstChild(self.root)
1210        while item:
1211            name = self.PatternTree.GetItemText(item)
1212            if 'PWDR' in name:
1213                names.append(name)
1214            item, cookie = self.PatternTree.GetNextChild(self.root, cookie)
1215        if names:
1216            dlg = wx.MultiChoiceDialog(self,'Select','Powder patterns to export',names)
1217            if dlg.ShowModal() == wx.ID_OK:
1218                sel = dlg.GetSelections()
1219                if sel[0] == 0:
1220                    exports = names[1:]
1221                else:
1222                    for x in sel:
1223                        exports.append(names[x])
1224            dlg.Destroy()
1225        if exports:
1226            dlg = wx.FileDialog(self, 'Choose output powder file name', '.', '', 
1227                'GSAS fxye file (*.fxye)|*.fxye|xye file (*.xye)|*.xye',
1228                wx.FD_SAVE|wx.FD_OVERWRITE_PROMPT)
1229            if self.dirname:
1230                dlg.SetDirectory(self.dirname)
1231            try:
1232                if dlg.ShowModal() == wx.ID_OK:
1233                    powderfile = dlg.GetPath()
1234                    if 'fxye' in powderfile:
1235                        G2IO.powderFxyeSave(self,exports,powderfile)
1236                    else:       #just xye
1237                        G2IO.powderXyeSave(self,exports,powderfile)
1238                    self.dirname = dlg.GetDirectory()
1239            finally:
1240                dlg.Destroy()
1241       
1242    def OnExportPeakList(self,event):
1243        dlg = wx.FileDialog(self, 'Choose output peak list file name', '.', '', 
1244            '(*.*)|*.*',wx.FD_SAVE|wx.FD_OVERWRITE_PROMPT)
1245        if self.dirname:
1246            dlg.SetDirectory(self.dirname)
1247        try:
1248            if dlg.ShowModal() == wx.ID_OK:
1249                self.peaklistfile = dlg.GetPath()
1250                file = open(self.peaklistfile,'w')               
1251                item, cookie = self.PatternTree.GetFirstChild(self.root)
1252                while item:
1253                    name = self.PatternTree.GetItemText(item)
1254                    if 'PWDR' in name:
1255                        item2, cookie2 = self.PatternTree.GetFirstChild(item)
1256                        while item2:
1257                            name2 = self.PatternTree.GetItemText(item2)
1258                            if name2 == 'Peak List':
1259                                peaks = self.PatternTree.GetItemPyData(item2)
1260                                file.write("%s \n" % (name+' Peak List'))               
1261                                for peak in peaks:
1262                                    file.write("%10.4f %12.2f %10.3f %10.3f \n" % \
1263                                        (peak[0],peak[2],peak[4],peak[6]))
1264                            item2, cookie2 = self.PatternTree.GetNextChild(item, cookie2)                           
1265                    item, cookie = self.PatternTree.GetNextChild(self.root, cookie)                           
1266                file.close()
1267                self.dirname = dlg.GetDirectory()
1268        finally:
1269            dlg.Destroy()
1270       
1271    def OnExportHKL(self,event):
1272        event.Skip()
1273       
1274    def OnExportPDF(self,event):
1275        #need S(Q) and G(R) to be saved here - probably best from selection?
1276        names = ['All']
1277        exports = []
1278        item, cookie = self.PatternTree.GetFirstChild(self.root)
1279        while item:
1280            name = self.PatternTree.GetItemText(item)
1281            if 'PDF' in name:
1282                names.append(name)
1283            item, cookie = self.PatternTree.GetNextChild(self.root, cookie)
1284        if names:
1285            dlg = wx.MultiChoiceDialog(self,'Select','PDF patterns to export',names)
1286            if dlg.ShowModal() == wx.ID_OK:
1287                sel = dlg.GetSelections()
1288                if sel[0] == 0:
1289                    exports = names[1:]
1290                else:
1291                    for x in sel:
1292                        exports.append(names[x])
1293            dlg.Destroy()
1294        if exports:
1295            G2IO.PDFSave(self,exports)
1296       
1297    def OnExportPhase(self,event):
1298        event.Skip()
1299       
1300    def OnExportCIF(self,event):
1301        event.Skip()
1302
1303    def OnMakePDFs(self,event):
1304        tth2q = lambda t,w:4.0*math.pi*sind(t/2.0)/w
1305        TextList = ['All PWDR']
1306        PDFlist = []
1307        Names = []
1308        if self.PatternTree.GetCount():
1309            id, cookie = self.PatternTree.GetFirstChild(self.root)
1310            while id:
1311                name = self.PatternTree.GetItemText(id)
1312                Names.append(name)
1313                if 'PWDR' in name:
1314                    TextList.append(name)
1315                id, cookie = self.PatternTree.GetNextChild(self.root, cookie)
1316            if len(TextList) == 1:
1317                self.ErrorDialog('Nothing to make PDFs for','There must be at least one "PWDR" pattern')
1318                return
1319            dlg = wx.MultiChoiceDialog(self,'Make PDF controls','Make PDF controls for:',TextList, wx.CHOICEDLG_STYLE)
1320            try:
1321                if dlg.ShowModal() == wx.ID_OK:
1322                    result = dlg.GetSelections()
1323                    for i in result: PDFlist.append(TextList[i])
1324                    if 0 in result:
1325                        PDFlist = [item for item in TextList if item[:4] == 'PWDR']                       
1326                    for item in PDFlist:
1327                        PWDRname = item[4:]
1328                        Id = self.PatternTree.AppendItem(parent=self.root,text='PDF '+PWDRname)
1329                        Data = {
1330                            'Sample':{'Name':item,'Mult':1.0,'Add':0.0},
1331                            'Sample Bkg.':{'Name':'','Mult':-1.0,'Add':0.0},
1332                            'Container':{'Name':'','Mult':-1.0,'Add':0.0},
1333                            'Container Bkg.':{'Name':'','Mult':-1.0,'Add':0.0},'ElList':{},
1334                            'Geometry':'Cylinder','Diam':1.0,'Pack':0.50,'Form Vol':10.0,
1335                            'DetType':'Image plate','ObliqCoeff':0.2,'Ruland':0.025,'QScaleLim':[0,100],
1336                            'Lorch':True,}
1337                        self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='PDF Controls'),Data)
1338                        self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='I(Q)'+PWDRname),[])       
1339                        self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='S(Q)'+PWDRname),[])       
1340                        self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='F(Q)'+PWDRname),[])       
1341                        self.PatternTree.SetItemPyData(self.PatternTree.AppendItem(Id,text='G(R)'+PWDRname),[])       
1342                self.ExportPDF.Enable(True)
1343            finally:
1344                dlg.Destroy()
1345       
1346    def OnRefine(self,event):
1347        self.OnFileSave(event)
1348        #works - but it'd be better if it could restore plots
1349        G2str.Refine(self.GSASprojectfile)
1350        dlg = wx.MessageDialog(self,'Load new result?','Refinement results',wx.OK|wx.CANCEL)
1351        try:
1352            if dlg.ShowModal() == wx.ID_OK:
1353                self.PatternTree.DeleteChildren(self.root)
1354                if self.HKL: self.HKL = []
1355                if self.G2plotNB.plotList:
1356                    self.G2plotNB.clear()
1357                G2IO.ProjFileOpen(self)
1358        finally:
1359            dlg.Destroy()
1360       
1361    def OnSolve(self,event):
1362        #works - but it'd be better if it could restore plots
1363        G2sol.Solve(self.GSASprojectfile)
1364        dlg = wx.MessageDialog(self,'Load new result?','Structure solution results',wx.OK|wx.CANCEL)
1365        try:
1366            if dlg.ShowModal() == wx.ID_OK:
1367                self.PatternTree.DeleteChildren(self.root)
1368                if self.HKL: self.HKL = []
1369                if self.G2plotNB.plotList:
1370                    self.G2plotNB.clear()
1371                G2IO.ProjFileOpen(self)
1372        finally:
1373            dlg.Destroy()
1374       
1375    def ErrorDialog(self,title,message):
1376        dlg = wx.MessageDialog(self, message, title,  wx.OK)
1377        try:
1378            result = dlg.ShowModal()
1379        finally:
1380            dlg.Destroy()
1381
1382    def OnHelpHelp(self, event):
1383        event.Skip()
1384       
1385    def OnHelpAbout(self, event):
1386        info = wx.AboutDialogInfo()
1387        info.Name = 'GSAS-II'
1388        info.Version = __version__
1389        info.Copyright = '''
1390Robert B. Von Dreele
1391Argonne National Laboratory(C)
1392This product includes software developed
1393by the UChicago Argonne, LLC, as
1394Operator of Argonne National Laboratory.         '''
1395        info.Description = '''
1396General Structure Analysis System - II
1397        '''
1398        wx.AboutBox(info)
1399       
1400class GSASIImain(wx.App):
1401    def OnInit(self):
1402        self.main = GSASII(None)
1403        self.main.Show()
1404        self.SetTopWindow(self.main)
1405        return True
1406
1407def main():
1408    application = GSASIImain(0)
1409    application.MainLoop()
1410
1411if __name__ == '__main__':
1412    main()
Note: See TracBrowser for help on using the repository browser.