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

Contents of /trunk/pygtk/gtkbrowser.py

Parent Directory Parent Directory | Revision Log Revision Log


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

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