/[ascend]/trunk/pygtk/gtkbrowser.py
ViewVC logotype

Contents of /trunk/pygtk/gtkbrowser.py

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1616 - (show annotations) (download) (as text)
Mon Sep 3 14:05:44 2007 UTC (17 years, 2 months ago) by jpye
File MIME type: text/x-python
File size: 37110 byte(s)
Added default ASCENDLIBRARY and ASCENDSOLVERS fetched on Windows from the Registry.
Updated installer to set these registry values at install time.
In packages.c, output to say what the default values are found to be.
Remove some redundant output in 'ascend' script.
1 import sys
2 try:
3 import loading
4 #loading.print_status("Loading PSYCO")
5 #try:
6 # import psyco
7 # psyco.full()
8 # print "Running with PSYCO optimisation..."
9 #except ImportError:
10 # pass
11
12 loading.print_status("Loading python standard libraries")
13
14 import pygtk
15 pygtk.require('2.0')
16 import gtk
17
18 import re
19 import urlparse
20 import optparse
21 import platform
22 import sys
23
24 if platform.system() != "Windows":
25 try:
26 import dl
27 _dlflags = dl.RTLD_GLOBAL|dl.RTLD_NOW
28 except:
29 # On platforms that unilaterally refuse to provide the 'dl' module
30 # we'll just set the value and see if it works.
31 loading.print_status("Setting dlopen flags","Python 'dl' module not available on this system")
32 _dlflags = 258
33 # This sets the flags for dlopen used by python so that the symbols in the
34 # ascend library are made available to libraries dlopened within ASCEND:
35 sys.setdlopenflags(_dlflags)
36
37
38
39 loading.print_status("Loading LIBASCEND/ascpy")
40 import ascpy
41 import os.path
42
43 loading.print_status("Loading PyGTK, glade, pango")
44
45 import gtk.glade
46 import pango
47
48 loading.load_matplotlib()
49
50 loading.print_status("Loading ASCEND python modules")
51 from preferences import * # loading/saving of .ini options
52 from solverparameters import * # 'solver parameters' window
53 from help import * # viewing help files
54 from incidencematrix import * # incidence/sparsity matrix matplotlib window
55 from observer import * # observer tab support
56 from properties import * # solver_var properties dialog
57 from varentry import * # for inputting of variables with units
58 from diagnose import * # for diagnosing block non-convergence
59 from solverreporter import * # solver status reporting
60 from modelview import * # model browser
61 from integrator import * # integrator dialog
62 from infodialog import * # general-purpose textual information dialog
63 from versioncheck import * # version check (contacts ascend.cruncher2.dyndns.org)
64 import config
65
66 loading.complete();
67
68 except RuntimeError, e:
69 print "ASCEND had problems starting up. Please report the following"
70 print "error message at http://mantis.cruncher2.dyndns.org/."
71 print "\n\nFull error message:",str(e)
72 print "\n\nPress ENTER to close this window."
73 sys.stdout.flush()
74 sys.stdin.readline();
75 sys.exit();
76
77 except ImportError, e:
78 print "\n\n------------------ ERROR ---------------------"
79 print "ASCEND had problems importing required models."
80 print "\nPlease ensure you have all the runtime prerequisites installed."
81 print "Please then report a bug if you continue to have problems."
82 print "\nFull error message:",str(e)
83 if platform.system()=="Windows":
84 print "\nYou will also need to report the contents of any popup error"
85 print "messages from Windows if any were shown."
86 print "\n\nPress ENTER to close this window."
87 sys.stdout.flush()
88 sys.stdin.readline();
89 sys.exit();
90
91 loading.print_status("Starting GUI")
92
93 # This is my first ever GUI code so please be nice :)
94 # But I *have* at least read
95 # http://www.joelonsoftware.com/uibook/chapters/fog0000000057.html
96 # and leafed through
97 # http://developer.gnome.org/projects/gup/hig/
98
99 # The fancy tree-view gizmo is the GtkTreeView object. See the article
100 # http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/300304
101 # for the original source code on which my implementation was based.
102
103 ESCAPE_KEY = 65307
104
105 HELP_ROOT = None
106
107 #======================================
108 # Browser is the main ASCEND library/model browser window
109
110 class Browser:
111
112 # ---------------------------------
113 # SETUP
114
115 def __init__(self,librarypath=None,assetspath=None):
116
117 if assetspath==None:
118 assetspath=config.PYGTK_ASSETS
119
120 #--------
121 # load the file referenced in the command line, if any
122
123 loading.print_status("Parsing options","CONFIG = %s"%config.VERSION)
124
125 parser = optparse.OptionParser(usage="%prog [[-m typename] file]", version="gtkbrowser $rev$" )
126 # add options here if we want
127
128 parser.add_option("-m", "--model"
129 ,action="store", type="string", dest="model"
130 ,help="specify the model to instantiate upon loading modules")
131
132 parser.add_option("--pygtk-assets"
133 ,action="store", type="string", dest="assets_dir"
134 ,help="override the configuration value for the location of assets"\
135 +" required by PyGTK for the ASCEND GUI, optional"
136 ,default=assetspath
137 )
138
139 parser.add_option("--library"
140 ,action="store", type="string", dest="library_path"
141 ,help="override the configuration value for the library path"
142 ,default=librarypath
143 )
144
145 parser.add_option("--no-auto-sim"
146 ,action="store_false", dest="auto_sim"
147 ,help="disable auto-instantiation of MODEL named as the file stem"
148 ,default=True
149 )
150
151 (self.options, args) = parser.parse_args()
152
153 #print "OPTIONS_______________:",self.options
154
155 self.assets_dir = self.options.assets_dir
156
157 self.observers = []
158 self.clip = None
159
160 #--------
161 # load up the preferences ini file
162
163 loading.print_status("Loading preferences")
164
165 self.prefs = Preferences()
166
167 _prefpath = self.prefs.getStringPref("Directories","librarypath",None)
168 _preffileopenpath = self.prefs.getStringPref("Directories","fileopenpath",None)
169
170 #--------
171 # set up library path and the path to use for File->Open dialogs
172
173 if self.options.library_path != None:
174 _path = os.path.abspath(self.options.library_path)
175 _pathsrc = "command line options"
176 # when a special path is specified, use the last path component as the file-open location
177 if platform.system()=="Windows":
178 self.fileopenpath = _path.split(":").pop()
179 else:
180 self.fileopenpath = _path.split(":").pop()
181 else:
182 if _prefpath:
183 _path = _prefpath
184 _pathsrc = "user preferences"
185 else:
186 # default setting, but override with Windows registry if present
187 _path = config.LIBRARY_PATH
188 _pathsrc = "default (config.py)"
189
190 if platform.system()=="Windows":
191 # use the registry
192 try:
193 import _winreg
194 x=_winreg.ConnectRegistry(None,_winreg.HKEY_LOCAL_MACHINE)
195 y= _winreg.OpenKey(x,r"SOFTWARE\ASCEND")
196 _regpath,t = _winreg.QueryValueEx(y,"ASCENDLIBRARY")
197 _winreg.CloseKey(y)
198 _winreg.CloseKey(x)
199 _path = _regpath
200 os.environ['ASCENDLIBRARY'] = _regpath
201 _pathsrc = "Windows registry"
202 except:
203 # otherwise keep using the default
204 pass
205
206 if _preffileopenpath:
207 self.fileopenpath = _preffileopenpath
208 else:
209 self.fileopenpath = _path
210
211 #--------
212 # Create the ASCXX 'Library' object
213
214 loading.print_status("Creating ASCEND 'Library' object","ASCENDLIBRARY = "+_path+" FROM "+_pathsrc)
215 self.library = ascpy.Library(str(_path))
216
217 self.sim = None
218
219 #-------------------
220 # Set up the window and main widget actions
221
222 self.glade_file = os.path.join(self.assets_dir,config.GLADE_FILE)
223
224 loading.print_status("Setting up windows") #,"GLADE_FILE = %s" % self.glade_file)
225
226 glade = gtk.glade.XML(self.glade_file,"browserwin")
227
228 self.window = glade.get_widget("browserwin")
229
230
231 if not self.window:
232 raise RuntimeError("Couldn't load window from glade file")
233
234 _display = self.window.get_screen().get_display().get_name()
235 _geom=self.prefs.getGeometrySizePosition(_display,"browserwin")
236 if _geom:
237 self.window.resize(_geom[0],_geom[1])
238 self.window.move(_geom[2],_geom[3])
239
240 self.window.connect("delete_event", self.delete_event)
241
242 self.browserpaned=glade.get_widget("browserpaned")
243 _geom2=self.prefs.getGeometryValue(_display,"browserpaned")
244 if _geom2:
245 self.browserpaned.set_position(_geom2)
246
247 buttons = ["open","reload","solve","integrate","check","methodrun"]
248 for n in buttons:
249 name = "%sbutton"%n
250 setattr(self,name,glade.get_widget(name))
251 getattr(self,name).connect("clicked",getattr(self,"%s_click"%n))
252
253 widgets = ["autotoggle","automenu","methodsel","maintabs","lowertabs","consolescroll","statusbar","browsermenu"]
254 for n in widgets:
255 setattr(self,n,glade.get_widget(n))
256
257 self.autotoggle.connect("toggled",self.auto_toggle)
258
259 self.show_solving_popup=glade.get_widget("show_solving_popup")
260 self.show_solving_popup.set_active(self.prefs.getBoolPref("SolverReporter","show_popup",True))
261 self.close_on_converged=glade.get_widget("close_on_converged")
262 self.close_on_converged.set_active(self.prefs.getBoolPref("SolverReporter","close_on_converged",True))
263 self.close_on_nonconverged=glade.get_widget("close_on_nonconverged")
264 self.close_on_nonconverged.set_active(self.prefs.getBoolPref("SolverReporter","close_on_nonconverged",True))
265 self.solver_engine=glade.get_widget("solver_engine")
266
267 self.use_relation_sharing=glade.get_widget("use_relation_sharing")
268 self.use_relation_sharing.set_active(self.prefs.getBoolPref("Compiler","use_relation_sharing",True))
269
270 self.use_binary_compilation=glade.get_widget("use_binary_compilation")
271 self.use_binary_compilation.set_active(self.prefs.getBoolPref("Compiler","use_binary_compilation",False))
272 self.use_binary_compilation.set_sensitive(self.use_relation_sharing.get_active())
273
274 glade.signal_autoconnect(self)
275
276 #-------
277 # Status icons
278
279 self.fixedimg = gtk.Image()
280 self.fixedimg.set_from_file(os.path.join(self.options.assets_dir,'locked.png'))
281
282 self.inactiveimg = gtk.Image()
283 self.inactiveimg.set_from_file(os.path.join(self.options.assets_dir,'unattached.png'))
284
285 self.iconstatusunknown = None
286 self.iconfixed = self.fixedimg.get_pixbuf()
287 self.iconsolved = self.window.render_icon(gtk.STOCK_YES,gtk.ICON_SIZE_MENU)
288 self.iconactive = self.window.render_icon(gtk.STOCK_NO,gtk.ICON_SIZE_MENU)
289 self.iconinactive = self.inactiveimg.get_pixbuf()
290 self.iconunsolved = None
291
292 self.statusicons={
293 ascpy.ASCXX_INST_STATUS_UNKNOWN: self.iconstatusunknown
294 ,ascpy.ASCXX_VAR_FIXED: self.iconfixed
295 ,ascpy.ASCXX_VAR_SOLVED: self.iconsolved
296 ,ascpy.ASCXX_VAR_ACTIVE: self.iconactive
297 ,ascpy.ASCXX_VAR_UNSOLVED: self.iconunsolved
298 ,ascpy.ASCXX_REL_INACTIVE: self.iconinactive
299 }
300
301
302 self.statusmessages={
303 ascpy.ASCXX_INST_STATUS_UNKNOWN: "Status unknown"
304 ,ascpy.ASCXX_VAR_FIXED: "Fixed"
305 ,ascpy.ASCXX_VAR_SOLVED: "Converged"
306 ,ascpy.ASCXX_VAR_ACTIVE: "Active (unconverged)"
307 ,ascpy.ASCXX_VAR_UNSOLVED: "Not yet visited"
308 ,ascpy.ASCXX_REL_INACTIVE: "Inactive"
309 }
310
311 #-------------------
312 # waitwin
313
314 self.waitwin = gtk.gdk.Window(self.window.window,
315 gtk.gdk.screen_width(),
316 gtk.gdk.screen_height(),
317 gtk.gdk.WINDOW_CHILD,
318 0,
319 gtk.gdk.INPUT_ONLY)
320
321 _cursor = gtk.gdk.Cursor(gtk.gdk.WATCH)
322 self.waitwin.set_cursor(_cursor)
323
324 #-------------------
325 # pixbufs to be used in the error listing
326
327 self.iconok = self.window.render_icon(gtk.STOCK_YES,gtk.ICON_SIZE_MENU)
328 self.iconinfo = self.window.render_icon(gtk.STOCK_DIALOG_INFO,gtk.ICON_SIZE_MENU)
329 self.iconwarning = self.window.render_icon(gtk.STOCK_DIALOG_WARNING,gtk.ICON_SIZE_MENU)
330 self.iconerror = self.window.render_icon(gtk.STOCK_DIALOG_ERROR,gtk.ICON_SIZE_MENU)
331
332 #--------------------
333 # pixbufs for solver_var status
334
335 #--------------------
336 # set up the error view
337
338 self.errorview = glade.get_widget("errorview")
339 errstorecolstypes = [gtk.gdk.Pixbuf,str,str,str,int]
340 self.errorstore = gtk.TreeStore(*errstorecolstypes)
341 errtitles = ["","Location","Message"];
342 self.errorview.set_model(self.errorstore)
343 self.errcols = [ gtk.TreeViewColumn() for _type in errstorecolstypes]
344
345 i = 0
346 for tvcolumn in self.errcols[:len(errtitles)]:
347 tvcolumn.set_title(errtitles[i])
348 self.errorview.append_column(tvcolumn)
349
350 if i>0:
351 _renderer = gtk.CellRendererText()
352 tvcolumn.pack_start(_renderer, True)
353 tvcolumn.add_attribute(_renderer, 'text', i)
354 if(i==2):
355 tvcolumn.add_attribute(_renderer, 'foreground', 3)
356 tvcolumn.add_attribute(_renderer, 'weight', 4)
357 else:
358 _renderer1 = gtk.CellRendererPixbuf()
359 tvcolumn.pack_start(_renderer1, False)
360 tvcolumn.add_attribute(_renderer1, 'pixbuf', int(0))
361
362 i = i + 1
363
364
365 #--------------------
366 # set up the error reporter callback
367 self.reporter = ascpy.getReporter()
368 self.reporter.setPythonErrorCallback(self.error_callback)
369
370
371 #-------
372 # Solver engine list
373
374 _slvlist = ascpy.getSolvers()
375 self.solver_engine_menu = gtk.Menu()
376 self.solver_engine_menu.show()
377 self.solver_engine.set_submenu(self.solver_engine_menu)
378 self.solver_engine_menu_dict = {}
379 _fmi = None
380 for _s in _slvlist:
381 _mi = gtk.RadioMenuItem(_fmi,_s.getName(),False)
382 if _fmi==None:
383 _fmi = _mi
384 _mi.show()
385 _mi.connect('toggled',self.on_select_solver_toggled,_s.getName())
386 self.solver_engine_menu.append(_mi)
387 self.solver_engine_menu_dict[_s.getName()]=_mi
388
389 _pref_solver = self.prefs.getStringPref("Solver","engine","QRSlv")
390 _mi = self.solver_engine_menu_dict.get(_pref_solver)
391 if _mi:
392 _mi.set_active(1)
393
394 #--------
395 # Assign an icon to the main window
396
397 self.icon = None
398 if config.ICON_EXTENSION:
399 _iconpath = ""
400 try:
401 _icon = gtk.Image()
402 _iconpath = os.path.join(self.assets_dir,'ascend'+config.ICON_EXTENSION)
403 _icon.set_from_file(_iconpath)
404 _iconpbuf = _icon.get_pixbuf()
405 self.window.set_icon(_iconpbuf)
406 self.icon = _iconpbuf
407 except Exception, e:
408 print "FAILED TO SET APPLICATION ICON PATH '%s': %s" % (_iconpath,str(e))
409 self.reporter.reportError("FAILED to set application icon '%s': %s"
410 % (_iconpath,str(e))
411 )
412
413 #-------------------
414 # set up the module view
415
416 self.modtank = {}
417 self.moduleview = glade.get_widget("moduleview")
418 modulestorecoltypes = [str, str, int] # bool=can-be-instantiated
419 self.modulestore = gtk.TreeStore(*modulestorecoltypes)
420 moduleviewtitles = ["Module name", "Filename"]
421 self.moduleview.set_model(self.modulestore)
422 self.modcols = [ gtk.TreeViewColumn() for _type in modulestorecoltypes]
423 i = 0
424 for modcol in self.modcols[:len(moduleviewtitles)]:
425 modcol.set_title(moduleviewtitles[i])
426 self.moduleview.append_column(modcol)
427 _renderer = gtk.CellRendererText()
428 modcol.pack_start(_renderer, True)
429 modcol.add_attribute(_renderer, 'text', i)
430 modcol.add_attribute(_renderer,'weight',2)
431 i = i + 1
432 self.moduleview.connect("row-activated", self.module_activated )
433
434 #--------------------
435 # set up the methods combobox
436
437 self.methodstore = gtk.ListStore(str)
438 self.methodsel.set_model(self.methodstore)
439 _methodrenderer = gtk.CellRendererText()
440 self.methodsel.pack_start(_methodrenderer, True)
441 self.methodsel.add_attribute(_methodrenderer, 'text',0)
442
443 #--------
444 # set up the instance browser view
445
446 self.modelview = ModelView(self, glade)
447
448 #--------
449 # set up the tabs
450 self.tabs = {}
451 self.activetab = None # most recent observer tab
452
453 #--------
454 # set the state of the 'auto' toggle
455
456 self.is_auto = self.prefs.getBoolPref("Browser","auto_solve",True)
457 self.autotoggle.set_active(self.is_auto)
458 self.automenu.set_active(self.is_auto)
459
460 #--------
461 # tell libascend about this 'browser' object
462
463 print dir(ascpy.Registry())
464 ascpy.Registry().set("browser",self)
465
466 #--------
467 # options
468
469 if(len(args)==1):
470 try:
471 self.do_open(args[0])
472 except RuntimeError,e:
473 self.reporter.reportError(str(e))
474 return
475
476 print "Options: ",self.options
477
478 _model = None
479 if self.options.model:
480 _model = self.options.model
481 print "MODEL: '%s'" % _model
482 elif self.options.auto_sim:
483 _head, _tail = os.path.split(args[0])
484 if(_tail):
485 _model, _ext = os.path.splitext(_tail)
486
487 if _model:
488 try:
489 _t=self.library.findType(_model)
490 try:
491 self.do_sim(_t)
492 if not self.options.model:
493 self.reporter.reportNote("Instantiated self-titled model '%s'" %_model)
494 except RuntimeError, e:
495 self.reporter.reportError("Failed to create instance of '%s': %s"
496 %(_model, str(e))
497 );
498 except RuntimeError, e:
499 if self.options.model:
500 self.reporter.reportError("Unknown model type '%s': %s"
501 %(_model, str(e))
502 );
503
504
505 #--------
506 # report absence of solvers if nec.
507
508 if not len(ascpy.getSolvers()):
509 print "NO SOLVERS LOADED!"
510 self.reporter.reportError( "No solvers were loaded! ASCEND is probably not configured correctly." )
511
512 #--------
513 # IPython console, if available
514
515 import console
516 console.create_widget(self)
517
518 def run(self):
519 self.window.show()
520 loading.print_status("ASCEND is now running")
521 gtk.main()
522
523 # ------------------
524 # SOLVER LIST
525
526 def set_solver(self,solvername):
527 """ this sets the active solver in the GUI, which is the default applied to newly instantiated models """
528 self.solver = ascpy.Solver(solvername)
529 self.prefs.setStringPref("Solver","engine",solvername)
530 self.reporter.reportNote("Set solver engine to '%s'" % solvername)
531
532 # --------------------------------------------
533 # MAJOR GUI COMMANDS
534
535 def on_fix_variable_activate(self,*args):
536 self.modelview.on_fix_variable_activate(*args)
537
538 def on_free_variable_activate(self,*args):
539 self.modelview.on_free_variable_activate(*args)
540
541 def on_select_solver_toggled(self,widget,solvername):
542 if widget.get_active():
543 self.set_solver(solvername)
544
545 def do_open(self,filename):
546 # TODO does the user want to lose their work?
547 # TODO do we need to chdir?
548
549 _context = self.statusbar.get_context_id("do_open")
550
551 self.errorstore.clear()
552 self.modelview.clear()
553
554 # self.library.clear()
555
556 print "Filename =",filename
557 self.statusbar.push(_context,"Loading '"+filename+"'")
558 try:
559 self.filename = filename
560 self.library.load(filename)
561 except RuntimeError,e:
562 self.statusbar.pop(_context)
563 raise
564
565 print "Statusbar =",self.statusbar
566 try:
567 self.statusbar.pop(_context)
568 except TypeError,e:
569 print "For some reason, a type error (context=%s,filename=%s): %s" % (_context,filename,e)
570
571 # Load the current list of modules into self.modules
572 self.modtank = {}
573 self.modulestore.clear()
574 modules = self.library.getModules()
575 #self.library.listModules()
576 try:
577 _lll=len(modules)
578 except:
579 _msg = "UNABLE TO ACCESS MODULES LIST. This is bad.\n"+\
580 "Check your SWIG configuration (check for warnings during build)."
581
582 self.reporter.reportError(_msg)
583 raise RuntimeError(_msg)
584
585 for m in reversed(modules):
586 _n = str( m.getName() )
587 _f = str( m.getFilename() )
588 #print "ADDING ROW name %s, file = %s" % (_n, _f)
589 _r = self.modulestore.append(None, [ _n, _f, pango.WEIGHT_NORMAL ])
590 for t in self.library.getModuleTypes(m):
591 _n = t.getName()
592 _hasparams = t.hasParameters()
593 if _hasparams:
594 _w = pango.WEIGHT_NORMAL
595 else:
596 _w = pango.WEIGHT_BOLD
597
598 #print "ADDING TYPE %s" % _n
599 _piter = self.modulestore.append(_r , [ _n, "", _w ])
600 _path = self.modulestore.get_path(_piter)
601 self.modtank[_path]=t
602
603 #print "DONE ADDING MODULES"
604
605 self.sim = None;
606 self.maintabs.set_current_page(0);
607
608 # See http://www.daa.com.au/pipermail/pygtk/2005-October/011303.html
609 # for details on how the 'wait cursor' is done.
610 def start_waiting(self, message):
611 self.waitcontext = self.statusbar.get_context_id("waiting")
612 self.statusbar.push(self.waitcontext,message)
613
614 if self.waitwin:
615 self.waitwin.show()
616
617 while gtk.events_pending():
618 gtk.main_iteration()
619
620 def stop_waiting(self):
621 if self.waitwin:
622 self.statusbar.pop(self.waitcontext)
623 self.waitwin.hide()
624
625 def do_sim(self, type_object):
626 self.sim = None;
627 # TODO: clear out old simulation first!
628
629 print "DO_SIM(%s)" % str(type_object.getName())
630 self.start_waiting("Compiling...")
631
632 try:
633 _v = self.prefs.getBoolPref("Compiler","use_relation_sharing",True)
634 ascpy.getCompiler().setUseRelationSharing(_v)
635
636 _v = self.prefs.getBoolPref("Compiler","use_binary_compilation",True)
637 ascpy.getCompiler().setBinaryCompilation(True)
638
639 self.sim = type_object.getSimulation(str(type_object.getName())+"_sim",False)
640
641 #self.reporter.reportNote("SIMULATION ASSIGNED")
642 except RuntimeError, e:
643 self.stop_waiting()
644 self.reporter.reportError(str(e))
645 return
646
647 self.stop_waiting()
648
649 # get method names and load them into the GUI
650 self.methodstore.clear()
651 _methods = self.sim.getType().getMethods()
652 _activemethod = None;
653 for _m in _methods:
654 _i = self.methodstore.append([_m.getName()])
655 if _m.getName()=="on_load":
656 self.methodsel.set_active_iter(_i)
657
658 self.modelview.setSimulation(self.sim)
659
660 # run the 'on_load' method
661 self.start_waiting("Running default method...")
662 try:
663 #self.reporter.reportNote("SIMULATION CREATED, RUNNING DEFAULT METHOD NOW...")
664 self.sim.runDefaultMethod()
665 except RuntimeError, e:
666 self.stop_waiting()
667 self.reporter.reportError(str(e))
668 return
669 self.stop_waiting()
670
671 self.modelview.refreshtree()
672
673 def do_solve_if_auto(self):
674 if self.is_auto:
675 self.sim.checkInstance()
676 self.do_solve()
677 else:
678 self.sim.processVarStatus()
679 self.modelview.refreshtree()
680
681 self.sync_observers()
682
683 def do_solve(self):
684 if not self.sim:
685 self.reporter.reportError("No model selected yet")
686 return
687
688 try:
689 self.sim.build()
690 except RuntimeError,e:
691 self.reporter.reportError("Couldn't build system: %s",str(e));
692 return
693
694 if not hasattr(self,'solver'):
695 self.reporter.reportError("No solver assigned!")
696 return
697
698 self.start_waiting("Solving with %s..." % self.solver.getName())
699
700 if self.prefs.getBoolPref("SolverReporter","show_popup",True):
701 reporter = PopupSolverReporter(self,self.sim.getNumVars())
702 else:
703 reporter = SimpleSolverReporter(self)
704
705 try:
706 self.sim.solve(self.solver,reporter)
707 except RuntimeError,e:
708 self.reporter.reportError(str(e))
709
710 self.stop_waiting()
711
712 self.modelview.refreshtree()
713
714 def do_integrate(self):
715 if not self.sim:
716 self.reporter.reportError("No model selected yet")
717 return
718
719 try:
720 self.sim.build()
721 except RuntimeError,e:
722 self.reporter.reportError("Couldn't build system: %s",str(e))
723 return
724
725 integwin = IntegratorWindow(self,self.sim)
726 _integratorreporter = integwin.run()
727 if _integratorreporter!=None:
728 _integratorreporter.run()
729 self.sim.processVarStatus()
730 self.modelview.refreshtree()
731
732
733 def do_check(self):
734 try:
735 self.sim.build()
736 except RuntimeError,e:
737 self.reporter.reportError("Couldn't build system: %s",str(e));
738 return
739
740 self.start_waiting("Checking system...")
741
742 try:
743 self.sim.checkInstance()
744 self.reporter.reportWarning("System instance check run, check above for error (if any).")
745 # the above gives output but doesn't throw errors or return a status.
746 # ... this is a problem (at the C level)
747
748 status = self.sim.checkDoF()
749 if status==ascpy.ASCXX_DOF_UNDERSPECIFIED:
750 self.on_show_fixable_variables_activate(None)
751 elif status==ascpy.ASCXX_DOF_OVERSPECIFIED:
752 self.on_show_freeable_variables_activate(None)
753 elif status==ascpy.ASCXX_DOF_STRUCT_SINGULAR:
754 if not self.sim.checkStructuralSingularity():
755 sing = self.sim.getSingularityInfo()
756 title = "Structural singularity"
757 text = title
758 msgs = {
759 "The singularity can be reduced by freeing the following variables" : sing.freeablevars
760 ,"Relations involved in the structural singularity" : sing.rels
761 ,"Variables involved in the structural singularity" : sing.vars
762 }
763 for k,v in msgs.iteritems():
764 text+="\n\n%s:" % k
765 if len(v):
766 _l = [j.getName() for j in v]
767 _l.sort()
768 text+= "\n\t" + "\n\t".join(_l)
769 else:
770 text += "\nnone"
771
772 _dialog = InfoDialog(self,self.window,text,title)
773 _dialog.run()
774 else:
775 self.reporter.reportNote("System DoF check OK")
776
777 except RuntimeError, e:
778 self.stop_waiting()
779 self.reporter.reportError(str(e))
780 return
781
782 self.stop_waiting()
783 self.modelview.refreshtree()
784
785 def do_method(self,method):
786 if not self.sim:
787 self.reporter.reportError("No model selected yet")
788
789 try:
790 self.sim.run(method)
791 except RuntimeError,e:
792 self.reporter.reportError(str(e))
793
794 self.sim.processVarStatus()
795 self.modelview.refreshtree()
796
797 def do_quit(self):
798 loading.print_status("Saving window location")
799 self.reporter.clearPythonErrorCallback()
800
801 _w,_h = self.window.get_size()
802 _t,_l = self.window.get_position()
803 _display = self.window.get_screen().get_display().get_name()
804 self.prefs.setGeometrySizePosition(_display,"browserwin",_w,_h,_t,_l );
805
806 _p = self.browserpaned.get_position()
807 self.prefs.setGeometryValue(_display,"browserpaned",_p);
808
809 loading.print_status("Saving current directory")
810 self.prefs.setStringPref("Directories","fileopenpath",self.fileopenpath)
811
812 self.prefs.setBoolPref("Browser","auto_solve",self.is_auto)
813
814 loading.print_status("Saving preferences")
815 # causes prefs to be saved unless they are still being used elsewher
816 del(self.prefs)
817
818 loading.print_status("Clearing error callback")
819 self.reporter.clearPythonErrorCallback()
820
821 loading.print_status("Closing down GTK")
822 gtk.main_quit()
823
824 loading.print_status("Clearing library")
825 self.library.clear()
826
827 loading.print_status("Quitting")
828
829 return False
830
831 def on_tools_sparsity_click(self,*args):
832
833 self.reporter.reportNote("Preparing incidence matrix...")
834 _im = self.sim.getIncidenceMatrix();
835
836 self.reporter.reportNote("Plotting incidence matrix...")
837
838 _sp = IncidenceMatrixWindow(_im);
839 _sp.run();
840
841 def on_tools_repaint_tree_activate(self,*args):
842 self.reporter.reportNote("Repainting model view...")
843 self.modelview.refreshtree()
844
845 def on_diagnose_blocks_click(self,*args):
846 try:
847 _bl = self.sim.getActiveBlock()
848 except RuntimeError, e:
849 self.reporter.reportError(str(e))
850 return
851 _db = DiagnoseWindow(self,_bl)
852 _db.run();
853
854 def on_add_observer_click(self,*args):
855 self.create_observer()
856
857 def on_keep_observed_click(self,*args):
858 print "KEEPING..."
859 if len(self.observers) <= 0:
860 self.reporter.reportError("No observer defined!")
861 return
862 self.tabs[self.currentobservertab].do_add_row()
863
864 def on_copy_observer_matrix_click(self,*args):
865 if self.clip == None:
866 self.clip = gtk.Clipboard()
867
868 if len(self.observers) <= 0:
869 self.reporter.reportError("No observer defined!")
870 return
871 self.tabs[self.currentobservertab].copy_to_clipboard(self.clip)
872
873 def on_use_relation_sharing_toggle(self,checkmenuitem,*args):
874 _v = checkmenuitem.get_active()
875 self.prefs.setBoolPref("Compiler","use_relation_sharing",_v)
876 self.reporter.reportNote("Relation sharing set to "+str(_v))
877 self.use_binary_compilation.set_sensitive(_v);
878
879 def on_use_binary_compilation_toggle(self,checkmenuitem,*args):
880 _v = checkmenuitem.get_active()
881 self.prefs.setBoolPref("Compiler","use_binary_compilation",_v)
882 self.reporter.reportNote("Binary compilation set to "+str(_v))
883
884 def on_show_solving_popup_toggle(self,checkmenuitem,*args):
885 _v = checkmenuitem.get_active()
886 self.prefs.setBoolPref("SolverReporter","show_popup",_v)
887 print "SET TO",_v
888
889 def on_close_on_converged_toggle(self,checkmenuitem,*args):
890 _v = checkmenuitem.get_active()
891 self.prefs.setBoolPref("SolverReporter","close_on_converged",_v)
892
893 def on_close_on_nonconverged_toggle(self,checkmenuitem,*args):
894 _v = checkmenuitem.get_active()
895 self.prefs.setBoolPref("SolverReporter","close_on_nonconverged",_v)
896
897 def on_show_variables_near_bounds_activate(self,*args):
898 _epsilon = 1e-4;
899 text = "Variables Near Bounds"
900 title=text;
901 text += "\n"
902 _vars = self.sim.getVariablesNearBounds(_epsilon)
903 if len(_vars):
904 for _v in _vars:
905 text += "\n%s"%_v.getName()
906 else:
907 text +="\nnone"
908 _dialog = InfoDialog(self,self.window,text,title)
909 _dialog.run()
910
911 def on_show_vars_far_from_nominals_activate(self,*args):
912 _bignum = self.prefs.getRealPref("Browser","far_from_nominals",10);
913 text = "Variables Far from Nominals"
914 title=text;
915 text += "\n"
916 _vars = self.sim.getVariablesFarFromNominals(_bignum)
917 if len(_vars):
918 for _v in _vars:
919 text += "\n%s"%_v.getName()
920 else:
921 text +="\nnone"
922
923 text+="\n\nAbove calculated using a relative error of %f" % float(_bignum)
924 text+="\nModify this value in .ascend.ini, section '[Browser]', key 'far_from_nominals'."
925 _dialog = InfoDialog(self,self.window,text,title)
926 _dialog.run()
927
928 # --------------------------------------------
929 # MODULE LIST
930
931 def module_activated(self, treeview, path, column, *args):
932 modules = self.library.getModules()
933 print "PATH",path
934 if len(path)==1:
935 self.reporter.reportNote("Launching of external editor not yet implemented")
936 elif len(path)==2:
937 if(self.modtank.has_key(path)):
938 _type = self.modtank[path];
939 self.reporter.reportNote("Creating simulation for type %s" % str(_type.getName()) )
940 self.do_sim(_type)
941 else:
942 self.reporter.reportError("Didn't find type corresponding to row")
943
944 # ----------------------------------
945 # ERROR PANEL
946
947 def get_error_row_data(self,sev,filename,line,msg):
948 try:
949 _sevicon = {
950 0 : self.iconok
951 ,1 : self.iconinfo
952 ,2 : self.iconwarning
953 ,4 : self.iconerror
954 ,8 : self.iconinfo
955 ,16 : self.iconwarning
956 ,32 : self.iconerror
957 ,64 : self.iconerror
958 }[sev]
959 except KeyError:
960 _sevicon = self.iconerror
961
962 _fontweight = pango.WEIGHT_NORMAL
963 if sev==32 or sev==64:
964 _fontweight = pango.WEIGHT_BOLD
965
966 _fgcolor = "black"
967 if sev==8:
968 _fgcolor = "#888800"
969 elif sev==16:
970 _fgcolor = "#884400"
971 elif sev==32 or sev==64:
972 _fgcolor = "#880000"
973 elif sev==0:
974 _fgcolor = BROWSER_FIXED_COLOR
975
976 if not filename and not line:
977 _fileline = ""
978 else:
979 if(len(filename) > 25):
980 filename = "..."+filename[-22:]
981 _fileline = filename + ":" + str(line)
982
983 _res = (_sevicon,_fileline,msg.rstrip(),_fgcolor,_fontweight)
984 #print _res
985 return _res
986
987 def error_callback(self,sev,filename,line,msg):
988 #print "SEV =",sev
989 #print "FILENAME =",filename
990 #print "LINE =",line
991 #print "MSG =",msg
992 pos = self.errorstore.append(None, self.get_error_row_data(sev, filename,line,msg))
993 path = self.errorstore.get_path(pos)
994 col = self.errorview.get_column(3)
995 self.errorview.scroll_to_cell(path,col)
996 return 0;
997
998 # --------------------------------
999 # BUTTON METHODS
1000
1001 def open_click(self,*args):
1002 #loading.print_status("CURRENT FILEOPENPATH is",self.fileopenpath)
1003 dialog = gtk.FileChooserDialog("Open ASCEND model...",
1004 self.window,
1005 gtk.FILE_CHOOSER_ACTION_OPEN,
1006 (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OPEN, gtk.RESPONSE_OK)
1007 )
1008 dialog.set_current_folder(self.fileopenpath)
1009 dialog.set_default_response(gtk.RESPONSE_OK)
1010 dialog.set_transient_for(self.window)
1011 dialog.set_modal(True)
1012
1013 filter = gtk.FileFilter()
1014 filter.set_name("*.a4c, *.a4l")
1015 filter.add_pattern("*.[Aa]4[Cc]")
1016 filter.add_pattern("*.[Aa]4[Ll]")
1017 dialog.add_filter(filter)
1018
1019 filter = gtk.FileFilter()
1020 filter.set_name("All files")
1021 filter.add_pattern("*")
1022 dialog.add_filter(filter)
1023
1024 response = dialog.run()
1025 _filename = dialog.get_filename()
1026 print "\nFILENAME SELECTED:",_filename
1027
1028 _path = dialog.get_current_folder()
1029 if _path:
1030 self.fileopenpath = _path
1031
1032 dialog.hide()
1033
1034 if response == gtk.RESPONSE_OK:
1035 self.reporter.reportNote("File %s selected." % dialog.get_filename() )
1036 self.library.clear()
1037 self.do_open( _filename)
1038
1039 def reload_click(self,*args):
1040 _type = None
1041 if(self.sim):
1042 _type = self.sim.getType().getName().toString();
1043
1044 self.library.clear()
1045
1046 try:
1047 self.do_open(self.filename)
1048 if _type:
1049 _t = self.library.findType(_type)
1050 self.do_sim(_t)
1051 except RuntimeError,e:
1052 self.reporter.reportError(str(e))
1053
1054 def props_activate(self,widget,*args):
1055 return self.modelview.props_activate(self,widget,*args)
1056
1057 def observe_activate(self,widget,*args):
1058 return self.modelview.observe_activate(self,widget,*args)
1059
1060 def solve_click(self,*args):
1061 #self.reporter.reportError("Solving simulation '" + self.sim.getName().toString() +"'...")
1062 self.do_solve()
1063
1064 def console_click(self,*args):
1065 self.lowertabs.set_current_page(1)
1066 self.consoletext.grab_focus()
1067
1068 def integrate_click(self,*args):
1069 self.do_integrate()
1070
1071 def check_click(self,*args):
1072 self.do_check()
1073 #self.reporter.reportError("CHECK clicked")
1074
1075 def preferences_click(self,*args):
1076 if not self.sim:
1077 self.reporter.reportError("No simulation created yet!");
1078 self.sim.setSolver(self.solver)
1079 _params = self.sim.getParameters()
1080 _paramswin = SolverParametersWindow(
1081 browser=self
1082 ,params=_params
1083 ,name=self.solver.getName()
1084 )
1085 if _paramswin.run() == gtk.RESPONSE_OK:
1086 print "PARAMS UPDATED"
1087 self.sim.setParameters(_paramswin.params)
1088 else:
1089 print "PARAMS NOT UPDATED"
1090
1091 def methodrun_click(self,*args):
1092 _sel = self.methodsel.get_active_text()
1093 if _sel:
1094 _method = None
1095 _methods = self.sim.getType().getMethods()
1096 for _m in _methods:
1097 if _m.getName()==_sel:
1098 _method = _m
1099 if not _method:
1100 self.reporter.reportError("Method is not valid")
1101 return
1102 self.do_method(_method)
1103 else:
1104 self.reporter.reportError("No method selected")
1105
1106 def auto_toggle(self,button,*args):
1107 self.is_auto = button.get_active()
1108 if hasattr(self,'automenu'):
1109 self.automenu.set_active(self.is_auto)
1110 else:
1111 raise RuntimeError("no automenu")
1112
1113 #if self.is_auto:
1114 # self.reporter.reportSuccess("Auto mode is now ON")
1115 #else:
1116 # self.reporter.reportSuccess("Auto mode is now OFF")
1117
1118 def on_file_quit_click(self,*args):
1119 self.do_quit()
1120
1121 def on_tools_auto_toggle(self,checkmenuitem,*args):
1122 self.is_auto = checkmenuitem.get_active()
1123 self.autotoggle.set_active(self.is_auto)
1124
1125 def on_help_about_click(self,*args):
1126 _xml = gtk.glade.XML(self.glade_file,"aboutdialog")
1127 _about = _xml.get_widget("aboutdialog")
1128 _about.set_position(gtk.WIN_POS_CENTER_ON_PARENT)
1129 _about.set_transient_for(self.window);
1130 _about.set_version(config.VERSION)
1131 _about.run()
1132 _about.destroy()
1133
1134 def on_help_contents_click(self,*args):
1135 _help = Help(HELP_ROOT)
1136 _help.run()
1137
1138 def on_report_a_bug_click(self,*args):
1139 import urllib
1140 import platform
1141 _plat = str(platform.system())
1142 _version = config.VERSION
1143 _help = Help(
1144 url="http://ascendbugs.cheme.cmu.edu/report/?project_id=ascend&platform=%s&build=%s"
1145 % (_plat,_version)
1146 )
1147 _help.run()
1148
1149 def on_help_check_for_updates_click(self,*args):
1150 v = VersionCheck()
1151 title = "Check for updates"
1152 text = "Your version is %s\n" % config.VERSION
1153 try:
1154 v.check()
1155 if config.VERSION==v.latest:
1156 text += "You are running the latest released version"
1157 else:
1158 text += "Latest version is %s\n" % v.latest
1159 if v.info:
1160 text += "Get more info at %s\n" % v.info
1161 if v.download:
1162 text += "Download from %s\n" % v.download
1163 except Exception, e:
1164 text += "\nUnable to check version\n"
1165 text += str(e)
1166
1167 _dialog = InfoDialog(self,self.window,text,title)
1168 _dialog.run()
1169
1170 def on_show_fixable_variables_activate(self,*args):
1171 try:
1172 v = self.sim.getFixableVariables()
1173 except RuntimeError,e:
1174 self.reporter.reportError(str(e))
1175 text = "Fixable Variables"
1176 title = text
1177 text += "\n"
1178 if len(v):
1179 for var in v:
1180 text += "\n%s"%var
1181 else:
1182 text += "\nnone"
1183 _dialog = InfoDialog(self,self.window,text,title)
1184 _dialog.run()
1185
1186 def on_show_fixed_vars_activate(self,*args):
1187 try:
1188 v = self.sim.getFixedVariables()
1189 text = "Fixed Variables"
1190 title = text
1191 text += "\n"
1192 if len(v):
1193 for var in v:
1194 text += "\n%s"%var
1195 else:
1196 text += "\nnone"
1197 _dialog = InfoDialog(self,self.window,text,title)
1198 _dialog.run()
1199 except RuntimeError,e:
1200 self.reporter.reportError(str(e))
1201
1202 def on_show_freeable_variables_activate(self,*args):
1203 try:
1204 v = self.sim.getFreeableVariables()
1205 except RuntimeError,e:
1206 self.reporter.reportError(str(e))
1207
1208 text = "Freeable Variables"
1209 title = text
1210 text += "\n"
1211 if len(v):
1212 for var in v:
1213 text += "\n%s" % var
1214 else:
1215 text += "\nnone"
1216 _dialog = InfoDialog(self,self.window,text,title)
1217 _dialog.run()
1218
1219 def on_show_external_functions_activate(self,*args):
1220 v = self.library.getExtMethods()
1221 text = "External Functions"
1222 title = text
1223 text +="\nHere is the list of external functions currently present in"
1224 text +=" the Library:"
1225
1226 if len(v):
1227 for ext in v:
1228 text += "\n\n%s (%d inputs, %d outputs):" % \
1229 (ext.getName(), ext.getNumInputs(), ext.getNumOutputs())
1230 text += "\n%s" % ext.getHelp()
1231 else:
1232 text +="\n\nNone"
1233 _dialog = InfoDialog(self,self.window,text,title)
1234 _dialog.run()
1235
1236 def on_maintabs_switch_page(self,notebook,page,pagenum):
1237 print("Page switched to %d" % pagenum)
1238 if pagenum in self.tabs.keys():
1239 self.currentobservertab = pagenum
1240
1241 def create_observer(self,name=None):
1242 _xml = gtk.glade.XML(self.glade_file,"observervbox");
1243 _label = gtk.Label();
1244 _tab = self.maintabs.append_page(_xml.get_widget("observervbox"),_label);
1245 _obs = ObserverTab(xml=_xml, name=name, browser=self, tab=_tab)
1246 _label.set_text(_obs.name)
1247 self.observers.append(_obs)
1248 self.tabs[_tab] = _obs
1249 self.currentobservertab = _tab
1250 return _obs
1251
1252 def sync_observers(self):
1253 for _o in self.observers:
1254 _o.sync()
1255
1256 def delete_event(self, widget, event):
1257 self.do_quit()
1258 return False
1259
1260 def observe(self,instance):
1261 if len(self.observers) ==0:
1262 self.create_observer()
1263 _observer = self.tabs[self.currentobservertab]
1264 _observer.add_instance(instance)
1265
1266 if __name__ == "__main__":
1267 b = Browser();
1268 b.run()

john.pye@anu.edu.au
ViewVC Help
Powered by ViewVC 1.1.22