1 | #!/usr/bin/env python |
---|
2 | # -*- coding: utf-8 -*- |
---|
3 | #GSAS-II Data/Model Comparison |
---|
4 | ########### SVN repository information ################### |
---|
5 | # $Date: $ |
---|
6 | # $Author: toby $ |
---|
7 | # $Revision: $ |
---|
8 | # $URL: $ |
---|
9 | # $Id: $ |
---|
10 | ########### SVN repository information ################### |
---|
11 | ''' |
---|
12 | ''' |
---|
13 | |
---|
14 | #TODO: in OnDataTreeSelChanged want to plot patterns |
---|
15 | # Make PWDR unique (use histlist) |
---|
16 | # add graphics |
---|
17 | # implement project |
---|
18 | |
---|
19 | import sys |
---|
20 | import os |
---|
21 | import platform |
---|
22 | if '2' in platform.python_version_tuple()[0]: |
---|
23 | import cPickle |
---|
24 | else: |
---|
25 | try: |
---|
26 | import _pickle as cPickle |
---|
27 | except: |
---|
28 | print('Warning: failed to import the optimized Py3 pickle (_pickle)') |
---|
29 | import pickle as cPickle |
---|
30 | |
---|
31 | import wx |
---|
32 | import numpy as np |
---|
33 | import matplotlib as mpl |
---|
34 | try: |
---|
35 | import OpenGL as ogl |
---|
36 | except ImportError: |
---|
37 | pass |
---|
38 | import scipy as sp |
---|
39 | |
---|
40 | import GSASIIpath |
---|
41 | GSASIIpath.SetVersionNumber("$Revision: 4154 $") |
---|
42 | import GSASIIfiles as G2fil |
---|
43 | import GSASIIplot as G2plt |
---|
44 | import GSASIIctrlGUI as G2G |
---|
45 | import GSASIIobj as G2obj |
---|
46 | |
---|
47 | __version__ = '0.0.1' |
---|
48 | |
---|
49 | def cPickleLoad(fp): |
---|
50 | if '2' in platform.python_version_tuple()[0]: |
---|
51 | return cPickle.load(fp) |
---|
52 | else: |
---|
53 | return cPickle.load(fp,encoding='latin-1') |
---|
54 | |
---|
55 | def main(application): |
---|
56 | '''Start up the GSAS-II GUI''' |
---|
57 | knownVersions = ['2.7','3.6','3.7','3.8'] |
---|
58 | if platform.python_version()[:3] not in knownVersions: |
---|
59 | dlg = wx.MessageDialog(None, |
---|
60 | 'GSAS-II requires Python 2.7.x or 3.6+\n Yours is '+sys.version.split()[0], |
---|
61 | 'Python version error', wx.OK) |
---|
62 | try: |
---|
63 | dlg.ShowModal() |
---|
64 | finally: |
---|
65 | dlg.Destroy() |
---|
66 | sys.exit() |
---|
67 | |
---|
68 | application.main = MakeTopWindow(None) # application.main is the main wx.Frame |
---|
69 | application.SetTopWindow(application.main) |
---|
70 | # save the current package versions |
---|
71 | application.main.PackageVersions = G2fil.get_python_versions([wx, mpl, np, sp, ogl]) |
---|
72 | try: |
---|
73 | application.SetAppDisplayName('GSAS-II Compare') |
---|
74 | except: |
---|
75 | pass |
---|
76 | #application.GetTopWindow().SendSizeEvent() |
---|
77 | application.GetTopWindow().Show(True) |
---|
78 | return application.GetTopWindow() |
---|
79 | |
---|
80 | class MakeTopWindow(wx.Frame): |
---|
81 | '''Define the main frame and its associated menu items |
---|
82 | ''' |
---|
83 | def __init__(self, parent): |
---|
84 | size = wx.Size(700,450) |
---|
85 | wx.Frame.__init__(self, name='dComp', parent=parent, |
---|
86 | size=size,style=wx.DEFAULT_FRAME_STYLE, title='GSAS-II data/model comparison') |
---|
87 | # plot window |
---|
88 | self.plotFrame = wx.Frame(None,-1,'dComp Plots',size=size, |
---|
89 | style=wx.DEFAULT_FRAME_STYLE ^ wx.CLOSE_BOX) |
---|
90 | self.G2plotNB = G2plt.G2PlotNoteBook(self.plotFrame,G2frame=self) |
---|
91 | self.plotFrame.Show() |
---|
92 | # menus |
---|
93 | Frame = self.GetTopLevelParent() # same as self |
---|
94 | Menu = wx.MenuBar() |
---|
95 | File = wx.Menu(title='') |
---|
96 | Menu.Append(menu=File, title='&File') |
---|
97 | item = File.Append(wx.ID_ANY,'&Import project...\tCtrl+O','Open a GSAS-II project file (*.gpx)') |
---|
98 | self.Bind(wx.EVT_MENU, self.onLoadGPX, id=item.GetId()) |
---|
99 | # item = File.Append(wx.ID_ANY,'&Import selected...','Open a GSAS-II project file (*.gpx)') |
---|
100 | # self.Bind(wx.EVT_MENU, self.onLoadSel, id=item.GetId()) |
---|
101 | |
---|
102 | self.Mode = wx.Menu(title='') |
---|
103 | Menu.Append(menu=self.Mode, title='&Mode') |
---|
104 | self.wxID_Mode = {} |
---|
105 | for m in "Histogram","Phase","Project": |
---|
106 | i = self.wxID_Mode[m] = wx.NewId() |
---|
107 | item = self.Mode.AppendRadioItem(i,m,'Display {}s'.format(m)) |
---|
108 | self.Bind(wx.EVT_MENU, self.onRefresh, id=item.GetId()) |
---|
109 | item = self.Mode.Append(wx.ID_ANY,'Set histogram filter','Set a filter for histograms to display') |
---|
110 | self.Bind(wx.EVT_MENU, self.onHistFilter, id=item.GetId()) |
---|
111 | |
---|
112 | Frame.SetMenuBar(Menu) |
---|
113 | # status bar |
---|
114 | self.Status = self.CreateStatusBar() |
---|
115 | self.Status.SetFieldsCount(2) |
---|
116 | # split the frame and add the tree |
---|
117 | self.mainPanel = wx.SplitterWindow(self, wx.ID_ANY, style=wx.SP_LIVE_UPDATE|wx.SP_3D) |
---|
118 | self.mainPanel.SetMinimumPaneSize(100) |
---|
119 | self.treePanel = wx.Panel(self.mainPanel, wx.ID_ANY, |
---|
120 | style = wx.TAB_TRAVERSAL|wx.SUNKEN_BORDER) |
---|
121 | |
---|
122 | # self.dataWindow = G2DataWindow(self.mainPanel) |
---|
123 | self.dataWindow = wx.ScrolledWindow(self.mainPanel) |
---|
124 | dataSizer = wx.BoxSizer(wx.VERTICAL) |
---|
125 | self.dataWindow.SetSizer(dataSizer) |
---|
126 | self.mainPanel.SplitVertically(self.treePanel, self.dataWindow, 200) |
---|
127 | self.Status.SetStatusWidths([200,-1]) # make these match? |
---|
128 | |
---|
129 | treeSizer = wx.BoxSizer(wx.VERTICAL) |
---|
130 | self.treePanel.SetSizer(treeSizer) |
---|
131 | self.GPXtree = G2G.G2TreeCtrl(id=wx.ID_ANY, |
---|
132 | parent=self.treePanel, size=self.treePanel.GetClientSize(),style=wx.TR_DEFAULT_STYLE ) |
---|
133 | TreeId = self.GPXtree.Id |
---|
134 | |
---|
135 | treeSizer.Add(self.GPXtree,1,wx.EXPAND|wx.ALL,0) |
---|
136 | #self.GPXtree.Bind(wx.EVT_TREE_SEL_CHANGED,self.OnDataTreeSelChanged) |
---|
137 | self.GPXtree.Bind(wx.EVT_TREE_SEL_CHANGED,self.OnDataTreeSelChanged) |
---|
138 | # self.GPXtree.Bind(wx.EVT_TREE_ITEM_RIGHT_CLICK,self.OnDataTreeSelChanged) |
---|
139 | # self.GPXtree.Bind(wx.EVT_TREE_ITEM_COLLAPSED, |
---|
140 | # self.OnGPXtreeItemCollapsed, id=TreeId) |
---|
141 | #self.GPXtree.Bind(wx.EVT_TREE_ITEM_EXPANDED, |
---|
142 | # self.OnGPXtreeItemExpanded, id=TreeId) |
---|
143 | # self.GPXtree.Bind(wx.EVT_TREE_DELETE_ITEM, |
---|
144 | # self.OnGPXtreeItemDelete, id=TreeId) |
---|
145 | # self.GPXtree.Bind(wx.EVT_TREE_KEY_DOWN, |
---|
146 | # self.OnGPXtreeKeyDown, id=TreeId) |
---|
147 | # self.GPXtree.Bind(wx.EVT_TREE_BEGIN_RDRAG, |
---|
148 | # self.OnGPXtreeBeginRDrag, id=TreeId) |
---|
149 | # self.GPXtree.Bind(wx.EVT_TREE_END_DRAG, |
---|
150 | # self.OnGPXtreeEndDrag, id=TreeId) |
---|
151 | self.root = self.GPXtree.root |
---|
152 | self.Bind(wx.EVT_CLOSE, lambda event: sys.exit()) |
---|
153 | |
---|
154 | self.fileList = [] # list of files read for use in Reload |
---|
155 | self.histList = [] # list of histograms loaded for unique naming |
---|
156 | |
---|
157 | self.PWDRfilter = None |
---|
158 | |
---|
159 | def SelectGPX(self): |
---|
160 | '''Select a .GPX file to be read |
---|
161 | ''' |
---|
162 | dlg = wx.FileDialog(self, 'Choose GSAS-II project file', |
---|
163 | wildcard='GSAS-II project file (*.gpx)|*.gpx',style=wx.FD_OPEN) |
---|
164 | try: |
---|
165 | if dlg.ShowModal() != wx.ID_OK: return |
---|
166 | fil = os.path.splitext(dlg.GetPath())[0]+'.gpx' |
---|
167 | finally: |
---|
168 | dlg.Destroy() |
---|
169 | if os.path.exists(fil): |
---|
170 | self.fileList.append([fil,'GPX']) |
---|
171 | return fil |
---|
172 | else: |
---|
173 | print('File {} not found, skipping'.format(fil)) |
---|
174 | return |
---|
175 | |
---|
176 | def getMode(self): |
---|
177 | '''returns the display mode (one of "Histogram","Phase","Project"). |
---|
178 | Could return '?' in case of an error. |
---|
179 | ''' |
---|
180 | for m in self.wxID_Mode: |
---|
181 | if self.Mode.FindItemById(self.wxID_Mode[m]).IsChecked(): |
---|
182 | break |
---|
183 | else: |
---|
184 | m = '?' |
---|
185 | return m |
---|
186 | |
---|
187 | def onRefresh(self,event): |
---|
188 | '''reread all files, in response to a change in mode, etc. |
---|
189 | ''' |
---|
190 | self.GPXtree.DeleteChildren(self.root) # delete tree contents |
---|
191 | self.histList = [] # clear list of loaded histograms |
---|
192 | for fil,mode in self.fileList: |
---|
193 | self.loadFile(fil) |
---|
194 | |
---|
195 | def loadFile(self,fil): |
---|
196 | '''read or reread a file |
---|
197 | ''' |
---|
198 | if self.getMode() == "Histogram": |
---|
199 | self.LoadPwdr(fil) |
---|
200 | elif self.getMode() == "Phase": |
---|
201 | self.LoadPhase(fil) |
---|
202 | elif self.getMode() == "Project": |
---|
203 | self.LoadProject(fil) |
---|
204 | else: |
---|
205 | print("mode not implemented") |
---|
206 | #raise Exception("mode not implemented") |
---|
207 | |
---|
208 | def onLoadGPX(self,event): |
---|
209 | '''Initial load of GPX file in response to a menu command |
---|
210 | ''' |
---|
211 | fil = self.SelectGPX() |
---|
212 | if not fil: return |
---|
213 | if not os.path.exists(fil): return |
---|
214 | self.fileList.append([fil,'GPX']) |
---|
215 | self.loadFile(fil) |
---|
216 | |
---|
217 | def LoadPwdr(self,fil): |
---|
218 | '''Load PWDR entries from a .GPX file to the tree. |
---|
219 | see :func:`GSASIIIO.ProjFileOpen` |
---|
220 | ''' |
---|
221 | G2frame = self |
---|
222 | filep = open(fil,'rb') |
---|
223 | shortname = os.path.splitext(os.path.split(fil)[1])[0] |
---|
224 | |
---|
225 | wx.BeginBusyCursor() |
---|
226 | histLoadList = [] |
---|
227 | try: |
---|
228 | while True: |
---|
229 | try: |
---|
230 | data = cPickleLoad(filep) |
---|
231 | except EOFError: |
---|
232 | break |
---|
233 | if not data[0][0].startswith('PWDR'): continue |
---|
234 | if self.PWDRfilter is not None: # implement filter |
---|
235 | if self.PWDRfilter not in data[0][0]: continue |
---|
236 | data[0][0] += ' (' |
---|
237 | data[0][0] += shortname |
---|
238 | data[0][0] += ')' |
---|
239 | histLoadList.append(data) |
---|
240 | |
---|
241 | except Exception as errmsg: |
---|
242 | if GSASIIpath.GetConfigValue('debug'): |
---|
243 | print('\nError reading GPX file:',errmsg) |
---|
244 | import traceback |
---|
245 | print (traceback.format_exc()) |
---|
246 | msg = wx.MessageDialog(G2frame,message="Error reading file "+ |
---|
247 | str(fil)+". This is not a current GSAS-II .gpx file", |
---|
248 | caption="Load Error",style=wx.ICON_ERROR | wx.OK | wx.STAY_ON_TOP) |
---|
249 | msg.ShowModal() |
---|
250 | finally: |
---|
251 | filep.close() |
---|
252 | wx.EndBusyCursor() |
---|
253 | |
---|
254 | datum = None |
---|
255 | for i,data in enumerate(histLoadList): |
---|
256 | datum = data[0] |
---|
257 | datum[0] = G2obj.MakeUniqueLabel(datum[0],self.histList) |
---|
258 | Id = G2frame.GPXtree.AppendItem(parent=G2frame.root,text=datum[0]) |
---|
259 | self.histList.append(datum[0]) |
---|
260 | # if 'ranId' not in datum[1][0]: # patch: add random Id if not present |
---|
261 | # datum[1][0]['ranId'] = ran.randint(0,sys.maxsize) |
---|
262 | G2frame.GPXtree.SetItemPyData(Id,datum[1][:3]) #temp. trim off junk (patch?) |
---|
263 | for datus in data[1:]: |
---|
264 | sub = G2frame.GPXtree.AppendItem(Id,datus[0]) |
---|
265 | #patch |
---|
266 | if datus[0] == 'Instrument Parameters' and len(datus[1]) == 1: |
---|
267 | if datum[0].startswith('PWDR'): |
---|
268 | datus[1] = [dict(zip(datus[1][3],zip(datus[1][0],datus[1][1],datus[1][2]))),{}] |
---|
269 | else: |
---|
270 | datus[1] = [dict(zip(datus[1][2],zip(datus[1][0],datus[1][1]))),{}] |
---|
271 | for item in datus[1][0]: #zip makes tuples - now make lists! |
---|
272 | datus[1][0][item] = list(datus[1][0][item]) |
---|
273 | #end patch |
---|
274 | G2frame.GPXtree.SetItemPyData(sub,datus[1]) |
---|
275 | if datum: # was anything loaded? |
---|
276 | print('project load successful for {}'.format(datum[0])) |
---|
277 | # G2frame.Status.SetStatusText('Mouse RB drag/drop to reorder',0) |
---|
278 | # G2frame.SetTitleByGPX() |
---|
279 | self.GPXtree.Expand(self.root) |
---|
280 | |
---|
281 | def onHistFilter(self,event): |
---|
282 | 'Load a filter string via a dialog in response to a menu event' |
---|
283 | lbl = '' |
---|
284 | if self.PWDRfilter is not None: |
---|
285 | lbl = self.PWDRfilter |
---|
286 | dlg = G2G.SingleStringDialog(self,'Set string', |
---|
287 | 'Set a string that must be in histogram name', |
---|
288 | lbl,size=(400,-1)) |
---|
289 | if dlg.Show(): |
---|
290 | if dlg.GetValue().strip() == '': |
---|
291 | self.PWDRfilter = None |
---|
292 | else: |
---|
293 | self.PWDRfilter = dlg.GetValue() |
---|
294 | dlg.Destroy() |
---|
295 | self.onRefresh(event) |
---|
296 | else: |
---|
297 | dlg.Destroy() |
---|
298 | |
---|
299 | def LoadPhase(self,fil): |
---|
300 | '''Load Phase entries from a .GPX file to the tree. |
---|
301 | see :func:`GSASIIIO.ProjFileOpen` |
---|
302 | ''' |
---|
303 | G2frame = self |
---|
304 | filep = open(fil,'rb') |
---|
305 | shortname = os.path.splitext(os.path.split(fil)[1])[0] |
---|
306 | |
---|
307 | wx.BeginBusyCursor() |
---|
308 | Phases = None |
---|
309 | try: |
---|
310 | while True: |
---|
311 | try: |
---|
312 | data = cPickleLoad(filep) |
---|
313 | except EOFError: |
---|
314 | break |
---|
315 | if not data[0][0].startswith('Phase'): continue |
---|
316 | Phases = data |
---|
317 | #if self.PWDRfilter is not None: # implement filter |
---|
318 | # if self.PWDRfilter not in data[0][0]: continue |
---|
319 | data[0][0] += ' (' |
---|
320 | if Phases: |
---|
321 | data[0][0] += shortname |
---|
322 | data[0][0] += ')' |
---|
323 | else: |
---|
324 | data[0][0] += shortname |
---|
325 | data[0][0] += 'has no phases)' |
---|
326 | Phases = data |
---|
327 | break |
---|
328 | |
---|
329 | except Exception as errmsg: |
---|
330 | if GSASIIpath.GetConfigValue('debug'): |
---|
331 | print('\nError reading GPX file:',errmsg) |
---|
332 | import traceback |
---|
333 | print (traceback.format_exc()) |
---|
334 | msg = wx.MessageDialog(G2frame,message="Error reading file "+ |
---|
335 | str(fil)+". This is not a current GSAS-II .gpx file", |
---|
336 | caption="Load Error",style=wx.ICON_ERROR | wx.OK | wx.STAY_ON_TOP) |
---|
337 | msg.ShowModal() |
---|
338 | finally: |
---|
339 | filep.close() |
---|
340 | wx.EndBusyCursor() |
---|
341 | |
---|
342 | datum = None |
---|
343 | if Phases: |
---|
344 | datum = data[0] |
---|
345 | #datum[0] = G2obj.MakeUniqueLabel(datum[0],self.histList) |
---|
346 | Id = G2frame.GPXtree.AppendItem(parent=G2frame.root,text=datum[0]) |
---|
347 | G2frame.GPXtree.SetItemPyData(Id,datum[1]) |
---|
348 | for datus in data[1:]: |
---|
349 | #datus[0] += ' (' |
---|
350 | #datus[0] += shortname |
---|
351 | #datus[0] += ')' |
---|
352 | sub = G2frame.GPXtree.AppendItem(Id,datus[0]) |
---|
353 | G2frame.GPXtree.SetItemPyData(sub,datus[1]) |
---|
354 | if datum: # was anything loaded? |
---|
355 | self.GPXtree.Expand(Id) |
---|
356 | print('project load successful for {}'.format(datum[0])) |
---|
357 | # G2frame.Status.SetStatusText('Mouse RB drag/drop to reorder',0) |
---|
358 | # G2frame.SetTitleByGPX() |
---|
359 | self.GPXtree.Expand(self.root) |
---|
360 | |
---|
361 | def LoadProject(self,fil): |
---|
362 | '''Load the Covariance entry from a .GPX file to the tree. |
---|
363 | see :func:`GSASIIIO.ProjFileOpen` |
---|
364 | ''' |
---|
365 | G2frame = self |
---|
366 | filep = open(fil,'rb') |
---|
367 | shortname = os.path.splitext(os.path.split(fil)[1])[0] |
---|
368 | |
---|
369 | wx.BeginBusyCursor() |
---|
370 | Phases = None |
---|
371 | try: |
---|
372 | while True: |
---|
373 | try: |
---|
374 | data = cPickleLoad(filep) |
---|
375 | except EOFError: |
---|
376 | break |
---|
377 | if not data[0][0].startswith('Covariance'): continue |
---|
378 | Covar = data[0] |
---|
379 | GSASIIpath.IPyBreak_base() |
---|
380 | #if self.PWDRfilter is not None: # implement filter |
---|
381 | # if self.PWDRfilter not in data[0][0]: continue |
---|
382 | Covar[0] = shortname + ' Covariance' |
---|
383 | Id = G2frame.GPXtree.AppendItem(parent=G2frame.root,text=Covar[0]) |
---|
384 | G2frame.GPXtree.SetItemPyData(Id,Covar[1]) |
---|
385 | break |
---|
386 | else: |
---|
387 | print("{} does not have refinement results".format(shortname)) |
---|
388 | except Exception as errmsg: |
---|
389 | if GSASIIpath.GetConfigValue('debug'): |
---|
390 | print('\nError reading GPX file:',errmsg) |
---|
391 | import traceback |
---|
392 | print (traceback.format_exc()) |
---|
393 | msg = wx.MessageDialog(G2frame,message="Error reading file "+ |
---|
394 | str(fil)+". This is not a current GSAS-II .gpx file", |
---|
395 | caption="Load Error",style=wx.ICON_ERROR | wx.OK | wx.STAY_ON_TOP) |
---|
396 | msg.ShowModal() |
---|
397 | finally: |
---|
398 | filep.close() |
---|
399 | wx.EndBusyCursor() |
---|
400 | self.GPXtree.Expand(self.root) |
---|
401 | |
---|
402 | def OnDataTreeSelChanged(self,event): |
---|
403 | item = event.GetItem() |
---|
404 | print('selected',item) |
---|
405 | |
---|
406 | #print(self.GPXtree._getTreeItemsList(item)) |
---|
407 | # pltNum = self.G2plotNB.nb.GetSelection() |
---|
408 | # print(pltNum) |
---|
409 | # if pltNum >= 0: #to avoid the startup with no plot! |
---|
410 | # self.G2plotNB.nb.GetPage(pltNum) |
---|
411 | # NewPlot = False |
---|
412 | # else: |
---|
413 | # NewPlot = True |
---|
414 | #if self.getMode() == "Histogram": |
---|
415 | #self.PatternId = self.PickId = item |
---|
416 | #G2plt.PlotPatterns(self,plotType='PWDR',newPlot=NewPlot) |
---|
417 | |
---|
418 | # def OnGPXtreeItemExpanded(self,event): |
---|
419 | # item = event.GetItem() |
---|
420 | # print('expanded',item) |
---|
421 | # print(self.GPXtree._getTreeItemsList(item)) |
---|
422 | # if item == self.root: |
---|
423 | # event.StopPropagation() |
---|
424 | # else: |
---|
425 | # event.Skip(False) |
---|
426 | |
---|
427 | if __name__ == '__main__': |
---|
428 | #if sys.platform == "darwin": |
---|
429 | # application = G2App(0) # create the GUI framework |
---|
430 | #else: |
---|
431 | application = wx.App(0) # create the GUI framework |
---|
432 | try: |
---|
433 | GSASIIpath.SetBinaryPath(True) |
---|
434 | except: |
---|
435 | print('Unable to run with current setup, do you want to update to the') |
---|
436 | try: |
---|
437 | if '2' in platform.python_version_tuple()[0]: |
---|
438 | ans = raw_input("latest GSAS-II version? Update ([Yes]/no): ") |
---|
439 | else: |
---|
440 | ans = input("latest GSAS-II version? Update ([Yes]/no): ") |
---|
441 | except: |
---|
442 | ans = 'no' |
---|
443 | if ans.strip().lower() == "no": |
---|
444 | import sys |
---|
445 | print('Exiting') |
---|
446 | sys.exit() |
---|
447 | print('Updating...') |
---|
448 | GSASIIpath.svnUpdateProcess() |
---|
449 | GSASIIpath.InvokeDebugOpts() |
---|
450 | Frame = main(application) # start the GUI |
---|
451 | argLoadlist = sys.argv[1:] |
---|
452 | if len(argLoadlist) == 0: |
---|
453 | argLoadlist = ['/Users/toby/Scratch/copy.gpx', |
---|
454 | '/Users/toby/Scratch/CW_YAG.gpx'] |
---|
455 | for arg in argLoadlist: |
---|
456 | fil = os.path.splitext(arg)[0] + '.gpx' |
---|
457 | if os.path.exists(fil): |
---|
458 | Frame.fileList.append([fil,'GPX']) |
---|
459 | Frame.loadFile(fil) |
---|
460 | else: |
---|
461 | print('File {} not found. Skipping'.format(fil)) |
---|
462 | application.MainLoop() |
---|