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

Contents of /trunk/pygtk/gtkbrowser.py

Parent Directory Parent Directory | Revision Log Revision Log


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

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