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

Contents of /trunk/pygtk/gtkbrowser.py

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2446 - (show annotations) (download) (as text)
Mon Apr 4 04:26:53 2011 UTC (11 years, 3 months ago) by jpye
File MIME type: text/x-python
File size: 39471 byte(s)
Add locale warning/error.
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 import locale
544 if locale.localeconv()['decimal_point'] != '.':
545 self.reporter.reportError(
546 """Incompatible locale settings detected. Please set your system local to one which
547 uses '.' as the decimal point separator, such as en_US or en_AU. Note that failing
548 to make this change will cause input and output values to be truncated.
549 For details, see http://ascendbugs.cheme.cmu.edu/view.php?id=337"""
550 )
551
552 def run(self):
553 self.window.show()
554 loading.print_status("ASCEND is now running")
555 loading.complete()
556 gtk.main()
557
558 # ------------------
559 # SOLVER LIST
560
561 def set_solver(self,solvername):
562 """ this sets the active solver in the GUI, which is the default applied to newly instantiated models """
563 self.solver = ascpy.Solver(solvername)
564 self.prefs.setStringPref("Solver","engine",solvername)
565 self.reporter.reportNote("Set solver engine to '%s'" % solvername)
566
567 # --------------------------------------------
568 # MAJOR GUI COMMANDS
569
570 def on_fix_variable_activate(self,*args):
571 if not self.sim:
572 self.reporter.reportError("No model selected yet")
573 return
574 self.modelview.on_fix_variable_activate(*args)
575
576 def on_free_variable_activate(self,*args):
577 if not self.sim:
578 self.reporter.reportError("No model selected yet")
579 return
580 self.modelview.on_free_variable_activate(*args)
581
582 def on_select_solver_toggled(self,widget,solvername):
583 if widget.get_active():
584 self.set_solver(solvername)
585
586 def do_open(self,filename):
587 # TODO does the user want to lose their work?
588 # TODO do we need to chdir?
589
590 _context = self.statusbar.get_context_id("do_open")
591
592 self.errorstore.clear()
593 self.modelview.clear()
594
595 # self.library.clear()
596
597 #print "Filename =",filename
598 self.statusbar.push(_context,"Loading '"+filename+"'")
599 try:
600 self.filename = filename
601 # call the low-level 'load' command...
602 self.library.load(filename)
603 except RuntimeError,e:
604 self.statusbar.pop(_context)
605 raise
606
607 try:
608 self.statusbar.pop(_context)
609 except TypeError,e:
610 print "For some reason, a type error (context=%s,filename=%s): %s" % (_context,filename,e)
611
612 # Load the current list of modules into self.modules
613 self.moduleview.refresh(self.library)
614
615 self.sim = None;
616 self.maintabs.set_current_page(0);
617
618 # See http://www.daa.com.au/pipermail/pygtk/2005-October/011303.html
619 # for details on how the 'wait cursor' is done.
620 def start_waiting(self, message):
621 self.waitcontext = self.statusbar.get_context_id("waiting")
622 self.statusbar.push(self.waitcontext,message)
623
624 if self.waitwin:
625 self.waitwin.show()
626
627 while gtk.events_pending():
628 gtk.main_iteration()
629
630 def stop_waiting(self):
631 if self.waitwin:
632 self.statusbar.pop(self.waitcontext)
633 self.waitwin.hide()
634
635 def do_sim(self, type_object):
636 self.sim = None;
637 # TODO: clear out old simulation first!
638
639 #print "DO_SIM(%s)" % str(type_object.getName())
640 self.start_waiting("Compiling...")
641
642 try:
643 _v = self.prefs.getBoolPref("Compiler","use_relation_sharing",True)
644 ascpy.getCompiler().setUseRelationSharing(_v)
645 print "Relation sharing set to",_v
646
647 _v = self.prefs.getBoolPref("Compiler","use_binary_compilation",False)
648 ascpy.getCompiler().setBinaryCompilation(_v)
649 print "Binary compilation set to",_v
650
651 self.sim = type_object.getSimulation(str(type_object.getName())+"_sim",False)
652
653 #self.reporter.reportNote("SIMULATION ASSIGNED")
654 except RuntimeError, e:
655 self.stop_waiting()
656 self.reporter.reportError(str(e))
657 return
658
659 self.stop_waiting()
660
661 # get method names and load them into the GUI
662 self.methodstore.clear()
663 _methods = self.sim.getType().getMethods()
664 _activemethod = None;
665 for _m in _methods:
666 _i = self.methodstore.append([_m.getName()])
667 if _m.getName()=="on_load":
668 self.methodsel.set_active_iter(_i)
669
670 self.modelview.setSimulation(self.sim)
671
672 # run the 'on_load' method
673 self.start_waiting("Running default method...")
674 try:
675 self.reporter.reportNote("SIMULATION CREATED, RUNNING DEFAULT METHOD NOW...")
676 self.sim.runDefaultMethod()
677 except RuntimeError, e:
678 self.stop_waiting()
679 self.reporter.reportError(str(e))
680 return
681 self.stop_waiting()
682
683 self.modelview.refreshtree()
684
685 def do_solve_if_auto(self):
686 if self.is_auto:
687 self.sim.checkInstance()
688 self.do_solve()
689 else:
690 try:
691 self.sim.processVarStatus()
692 except RuntimeError,e:
693 self.reporter.reportError(str(e))
694 self.modelview.refreshtree()
695
696 self.sync_observers()
697
698
699 def no_built_system(self):
700 """ check that the system is 'built', ready for use by the solver. """
701
702 if not self.sim:
703 self.reporter.reportError("No model selected yet")
704 return 1
705
706 try:
707 self.sim.build()
708 except RuntimeError,e:
709 self.reporter.reportError("Couldn't build system: %s" % str(e));
710 return 1
711
712 return 0;
713
714 def do_solve(self):
715 if self.no_built_system():
716 return
717
718 if not hasattr(self,'solver'):
719 self.reporter.reportError("No solver assigned!")
720 return
721
722 self.start_waiting("Solving with %s..." % self.solver.getName())
723
724 if self.prefs.getBoolPref("SolverReporter","show_popup",True):
725 reporter = PopupSolverReporter(self,self.sim.getNumVars())
726 else:
727 reporter = SimpleSolverReporter(self)
728
729 try:
730 self.sim.solve(self.solver,reporter)
731 except RuntimeError,e:
732 self.reporter.reportError(str(e))
733
734 self.stop_waiting()
735
736 self.modelview.refreshtree()
737
738 def do_integrate(self):
739 if self.no_built_system():
740 return
741
742 try:
743 self.sim.build()
744 except RuntimeError,e:
745 self.reporter.reportError("Couldn't build system: %s",str(e))
746 return
747
748 integwin = IntegratorWindow(self,self.sim)
749 _integratorreporter = integwin.run()
750 if _integratorreporter!=None:
751 _integratorreporter.run()
752 self.sim.processVarStatus()
753 self.modelview.refreshtree()
754
755
756 def do_check(self):
757 if self.no_built_system():
758 return
759
760 self.start_waiting("Checking system...")
761
762 try:
763 self.sim.checkInstance()
764 self.reporter.reportWarning("System instance check run, check above for error (if any).")
765 # the above gives output but doesn't throw errors or return a status.
766 # ... this is a problem (at the C level)
767
768 status = self.sim.checkDoF()
769 if status==ascpy.ASCXX_DOF_UNDERSPECIFIED:
770 self.on_show_fixable_variables_activate(None)
771 elif status==ascpy.ASCXX_DOF_OVERSPECIFIED:
772 self.on_show_freeable_variables_activate(None)
773 elif status==ascpy.ASCXX_DOF_STRUCT_SINGULAR:
774 if not self.sim.checkStructuralSingularity():
775 sing = self.sim.getSingularityInfo()
776 title = "Structural singularity"
777 text = title
778 msgs = {
779 "The singularity can be reduced by freeing the following variables" : sing.freeablevars
780 ,"Relations involved in the structural singularity" : sing.rels
781 ,"Variables involved in the structural singularity" : sing.vars
782 }
783 for k,v in msgs.iteritems():
784 text+="\n\n%s:" % k
785 if len(v):
786 _l = [j.getName() for j in v]
787 _l.sort()
788 text+= "\n\t" + "\n\t".join(_l)
789 else:
790 text += "\nnone"
791
792 _dialog = InfoDialog(self,self.window,text,title)
793 _dialog.run()
794 else:
795 self.reporter.reportNote("System DoF check OK")
796
797 except RuntimeError, e:
798 self.stop_waiting()
799 self.reporter.reportError(str(e))
800 return
801
802 self.stop_waiting()
803 self.modelview.refreshtree()
804
805 def do_method(self,method):
806
807 try:
808 self.sim.run(method)
809 except RuntimeError,e:
810 self.reporter.reportError(str(e))
811
812 self.sim.processVarStatus()
813 self.modelview.refreshtree()
814
815 def do_quit(self):
816 loading.print_status("Saving window location")
817 self.reporter.clearPythonErrorCallback()
818
819 _w,_h = self.window.get_size()
820 _t,_l = self.window.get_position()
821 _display = self.window.get_screen().get_display().get_name()
822 self.prefs.setGeometrySizePosition(_display,"browserwin",_w,_h,_t,_l );
823
824 _p = self.browserpaned.get_position()
825 self.prefs.setGeometryValue(_display,"browserpaned",_p);
826
827 loading.print_status("Saving current directory")
828 self.prefs.setStringPref("Directories","fileopenpath",self.fileopenpath)
829
830 self.prefs.setBoolPref("Browser","auto_solve",self.is_auto)
831
832 loading.print_status("Saving preferences")
833 # causes prefs to be saved unless they are still being used elsewher
834 del(self.prefs)
835
836 loading.print_status("Clearing error callback")
837 self.reporter.clearPythonErrorCallback()
838
839 loading.print_status("Closing down GTK")
840 gtk.main_quit()
841
842 loading.print_status("Clearing library")
843 self.library.clear()
844
845 loading.print_status("Quitting")
846
847 return False
848
849 def on_tools_sparsity_click(self,*args):
850
851 self.reporter.reportNote("Preparing incidence matrix...")
852 try:
853 _im = self.sim.getIncidenceMatrix()
854 self.reporter.reportNote("Plotting incidence matrix...")
855 _sp = IncidenceMatrixWindow(_im)
856 _sp.run()
857 except RuntimeError,e:
858 self.reporter.reportError(str(e))
859
860 def on_units_click(self,*args):
861 T = self.modelview.get_selected_type()
862 _un = UnitsDialog(self,T)
863 _un.run()
864
865 def on_tools_incidencegraph_click(self,*args):
866 self.reporter.reportNote("Preparing incidence graph...")
867 import tempfile
868 f,fname = tempfile.mkstemp(suffix=".png")
869 f = file(fname,'wb')
870 self.reporter.reportNote("temp file name = %s" % fname)
871 self.reporter.reportNote("file = %s" % f)
872 self.start_waiting("Creating incidence graph...")
873 try:
874 self.sim.write(f,'dot') # create a PNG file in f
875 except Exception,e:
876 self.stop_waiting()
877 self.reporter.reportError("Failed to create incidence graph: %s" % str(e))
878 return
879 f.close()
880 self.stop_waiting()
881 _ig = ImageWindow(self, self.window, fname, title="Incidence Graph", delete=True)
882 _ig.run()
883
884 def on_tools_repaint_tree_activate(self,*args):
885 self.reporter.reportNote("Repainting model view...")
886 self.modelview.refreshtree()
887
888 def on_diagnose_blocks_click(self,*args):
889 try:
890 _bl = self.sim.getActiveBlock()
891 _db = DiagnoseWindow(self,_bl)
892 _db.run();
893 except RuntimeError, e:
894 self.reporter.reportError(str(e))
895 return
896
897 def on_add_observer_click(self,*args):
898 self.create_observer()
899
900 def on_keep_observed_click(self,*args):
901 print "KEEPING..."
902 if len(self.observers) <= 0:
903 self.reporter.reportError("No observer defined!")
904 return
905 self.tabs[self.currentobservertab].do_add_row()
906
907 def on_copy_observer_matrix_click(self,*args):
908 if self.clip == None:
909 self.clip = gtk.Clipboard()
910
911 if len(self.observers) <= 0:
912 self.reporter.reportError("No observer defined!")
913 return
914 self.tabs[self.currentobservertab].copy_to_clipboard(self.clip)
915
916 def on_use_relation_sharing_toggle(self,checkmenuitem,*args):
917 _v = checkmenuitem.get_active()
918 self.prefs.setBoolPref("Compiler","use_relation_sharing",_v)
919 self.reporter.reportNote("Relation sharing set to "+str(_v))
920 self.use_binary_compilation.set_sensitive(_v);
921
922 def on_use_binary_compilation_toggle(self,checkmenuitem,*args):
923 _v = checkmenuitem.get_active()
924 self.prefs.setBoolPref("Compiler","use_binary_compilation",_v)
925 self.reporter.reportNote("Binary compilation set to "+str(_v))
926
927 def on_show_solving_popup_toggle(self,checkmenuitem,*args):
928 _v = checkmenuitem.get_active()
929 self.prefs.setBoolPref("SolverReporter","show_popup",_v)
930 print "SET TO",_v
931
932 def on_close_on_converged_toggle(self,checkmenuitem,*args):
933 _v = checkmenuitem.get_active()
934 self.prefs.setBoolPref("SolverReporter","close_on_converged",_v)
935
936 def on_close_on_nonconverged_toggle(self,checkmenuitem,*args):
937 _v = checkmenuitem.get_active()
938 self.prefs.setBoolPref("SolverReporter","close_on_nonconverged",_v)
939
940 def on_show_variables_near_bounds_activate(self,*args):
941 _epsilon = 1e-4;
942 try:
943 _vars = self.sim.getVariablesNearBounds(_epsilon)
944 except RuntimeError,e:
945 self.reporter.reportError("Unable to show variables near bounds:\n%s"%str(e))
946 return
947 text = "Variables Near Bounds"
948 title=text;
949 text += "\n"
950 if len(_vars):
951 for _v in _vars:
952 text += "\n%s"%_v.getName()
953 else:
954 text +="\nnone"
955 _dialog = InfoDialog(self,self.window,text,title)
956 _dialog.run()
957
958 def on_show_vars_far_from_nominals_activate(self,*args):
959 _bignum = self.prefs.getRealPref("Browser","far_from_nominals",10);
960 try:
961 _vars = self.sim.getVariablesFarFromNominals(_bignum)
962 except RuntimeError,e:
963 self.reporter.reportError("Unable to show variables far from nominals:\n%s"%str(e))
964 return
965 text = "Variables Far from Nominals"
966 title=text;
967 text += "\n"
968 if len(_vars):
969 for _v in _vars:
970 text += "\n%s"%_v.getName()
971 else:
972 text +="\nnone"
973
974 text+="\n\nAbove calculated using a relative error of %f" % float(_bignum)
975 text+="\nModify this value in .ascend.ini, section '[Browser]', key 'far_from_nominals'."
976 _dialog = InfoDialog(self,self.window,text,title)
977 _dialog.run()
978
979 # ----------------------------------
980 # ERROR PANEL
981
982 def get_error_row_data(self,sev,filename,line,msg):
983 try:
984 _sevicon = {
985 0 : self.iconok
986 ,1 : self.iconinfo
987 ,2 : self.iconwarning
988 ,4 : self.iconerror
989 ,8 : self.iconinfo
990 ,16 : self.iconwarning
991 ,32 : self.iconerror
992 ,64 : self.iconerror
993 }[sev]
994 except KeyError:
995 _sevicon = self.iconerror
996
997 _fontweight = pango.WEIGHT_NORMAL
998 if sev==32 or sev==64:
999 _fontweight = pango.WEIGHT_BOLD
1000
1001 _fgcolor = "black"
1002 if sev==8:
1003 _fgcolor = "#888800"
1004 elif sev==16:
1005 _fgcolor = "#884400"
1006 elif sev==32 or sev==64:
1007 _fgcolor = "#880000"
1008 elif sev==0:
1009 _fgcolor = BROWSER_FIXED_COLOR
1010
1011 if not filename and not line:
1012 _fileline = ""
1013 else:
1014 if(len(filename) > 25):
1015 filename = "..."+filename[-22:]
1016 _fileline = filename + ":" + str(line)
1017
1018 _res = (_sevicon,_fileline,msg.rstrip(),_fgcolor,_fontweight)
1019 #print _res
1020 return _res
1021
1022 def error_callback(self,sev,filename,line,msg):
1023 #print "SEV =",sev
1024 #print "FILENAME =",filename
1025 #print "LINE =",line
1026 #print "MSG =",msg
1027 pos = self.errorstore.append(None, self.get_error_row_data(sev, filename,line,msg))
1028 path = self.errorstore.get_path(pos)
1029 col = self.errorview.get_column(3)
1030 self.errorview.scroll_to_cell(path,col)
1031 return 0;
1032
1033 # --------------------------------
1034 # BUTTON METHODS
1035
1036 def open_click(self,*args):
1037 #loading.print_status("CURRENT FILEOPENPATH is",self.fileopenpath)
1038 dialog = gtk.FileChooserDialog("Open ASCEND model...",
1039 self.window,
1040 gtk.FILE_CHOOSER_ACTION_OPEN,
1041 (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OPEN, gtk.RESPONSE_OK)
1042 )
1043 dialog.set_current_folder(self.fileopenpath)
1044 dialog.set_default_response(gtk.RESPONSE_OK)
1045 dialog.set_transient_for(self.window)
1046 dialog.set_modal(True)
1047
1048 filter = gtk.FileFilter()
1049 filter.set_name("*.a4c, *.a4l")
1050 filter.add_pattern("*.[Aa]4[Cc]")
1051 filter.add_pattern("*.[Aa]4[Ll]")
1052 dialog.add_filter(filter)
1053
1054 filter = gtk.FileFilter()
1055 filter.set_name("All files")
1056 filter.add_pattern("*")
1057 dialog.add_filter(filter)
1058
1059 response = dialog.run()
1060 _filename = dialog.get_filename()
1061 print "\nFILENAME SELECTED:",_filename
1062
1063 _path = dialog.get_current_folder()
1064 if _path:
1065 self.fileopenpath = _path
1066
1067 dialog.hide()
1068
1069 if response == gtk.RESPONSE_OK:
1070 self.reporter.reportNote("File %s selected." % dialog.get_filename() )
1071 self.library.clear()
1072 try:
1073 self.do_open( _filename)
1074 except RuntimeError,e:
1075 self.reporter.reportError(str(e))
1076
1077 def reload_click(self,*args):
1078 _type = None
1079
1080 if not self.filename:
1081 self.reporter.reportError("No file loaded yet!")
1082 return
1083
1084 if self.sim:
1085 _type = self.sim.getType().getName().toString();
1086
1087 self.library.clear()
1088
1089 try:
1090 self.do_open(self.filename)
1091 if _type:
1092 _t = self.library.findType(_type)
1093 self.do_sim(_t)
1094 except RuntimeError,e:
1095 self.reporter.reportError(str(e))
1096
1097 def props_activate(self,widget,*args):
1098 return self.modelview.props_activate(self,widget,*args)
1099
1100 def observe_activate(self,widget,*args):
1101 return self.modelview.observe_activate(self,widget,*args)
1102
1103 def solve_click(self,*args):
1104 #self.reporter.reportError("Solving simulation '" + self.sim.getName().toString() +"'...")
1105 self.do_solve()
1106
1107 def console_click(self,*args):
1108 self.lowertabs.set_current_page(1)
1109 self.consoletext.grab_focus()
1110
1111 def integrate_click(self,*args):
1112 self.do_integrate()
1113
1114 def check_click(self,*args):
1115 self.do_check()
1116 #self.reporter.reportError("CHECK clicked")
1117
1118 def preferences_click(self,*args):
1119 if not self.sim:
1120 self.reporter.reportError("No simulation created yet!");
1121 self.sim.setSolver(self.solver)
1122 _params = self.sim.getParameters()
1123 _paramswin = SolverParametersWindow(
1124 browser=self
1125 ,params=_params
1126 ,name=self.solver.getName()
1127 )
1128 if _paramswin.run() == gtk.RESPONSE_OK:
1129 print "PARAMS UPDATED"
1130 self.sim.setParameters(_paramswin.params)
1131 else:
1132 print "PARAMS NOT UPDATED"
1133
1134 def methodrun_click(self,*args):
1135 _sel = self.methodsel.get_active_text()
1136 if _sel:
1137 _method = None
1138 _methods = self.sim.getType().getMethods()
1139 for _m in _methods:
1140 if _m.getName()==_sel:
1141 _method = _m
1142 if not _method:
1143 self.reporter.reportError("Method is not valid")
1144 return
1145 self.do_method(_method)
1146 else:
1147 self.reporter.reportError("No method selected")
1148
1149 def auto_toggle(self,button,*args):
1150 self.is_auto = button.get_active()
1151 if hasattr(self,'automenu'):
1152 self.automenu.set_active(self.is_auto)
1153 else:
1154 raise RuntimeError("no automenu")
1155
1156 #if self.is_auto:
1157 # self.reporter.reportSuccess("Auto mode is now ON")
1158 #else:
1159 # self.reporter.reportSuccess("Auto mode is now OFF")
1160
1161 def on_file_quit_click(self,*args):
1162 self.do_quit()
1163
1164 def on_tools_auto_toggle(self,checkmenuitem,*args):
1165 self.is_auto = checkmenuitem.get_active()
1166 self.autotoggle.set_active(self.is_auto)
1167
1168 def on_help_about_click(self,*args):
1169 _xml = gtk.glade.XML(self.glade_file,"aboutdialog")
1170 _about = _xml.get_widget("aboutdialog")
1171 _about.set_transient_for(self.window);
1172 _about.set_version(config.VERSION)
1173 _about.run()
1174 _about.destroy()
1175
1176 def on_help_contents_click(self,*args):
1177 _help = Help(HELP_ROOT)
1178 _help.run()
1179
1180 def on_report_a_bug_click(self,*args):
1181 import urllib
1182 import platform
1183 _plat = str(platform.system())
1184 _version = config.VERSION
1185 _help = Help(
1186 url="http://ascendbugs.cheme.cmu.edu/report/?project_id=ascend&platform=%s&build=%s"
1187 % (_plat,_version)
1188 )
1189 _help.run()
1190
1191 def on_help_check_for_updates_click(self,*args):
1192 v = VersionCheck()
1193 title = "Check for updates"
1194 text = "Your version is %s\n" % config.VERSION
1195 try:
1196 v.check()
1197 if config.VERSION==v.latest:
1198 text += "You are running the latest released version"
1199 else:
1200 text += "Latest version is %s\n" % v.latest
1201 if v.info:
1202 text += "Get more info at %s\n" % v.info
1203 if v.download:
1204 text += "Download from %s\n" % v.download
1205 except Exception, e:
1206 text += "\nUnable to check version\n"
1207 text += str(e)
1208
1209 _dialog = InfoDialog(self,self.window,text,title)
1210 _dialog.run()
1211
1212 def on_show_fixable_variables_activate(self,*args):
1213 try:
1214 v = self.sim.getFixableVariables()
1215 except Exception,e:
1216 self.reporter.reportError("Unable to show fixable variables: %s"%str(e))
1217 return
1218 text = "Fixable Variables"
1219 title = text
1220 text += "\n"
1221 if len(v):
1222 for var in v:
1223 text += "\n%s"%var
1224 else:
1225 text += "\nnone"
1226 _dialog = InfoDialog(self,self.window,text,title)
1227 _dialog.run()
1228
1229 def on_show_fixed_vars_activate(self,*args):
1230 try:
1231 v = self.sim.getFixedVariables()
1232 except RuntimeError,e:
1233 self.reporter.reportError("Unable to show fixed variables: %s"%str(e))
1234 return
1235 text = "%d fixed variables:" % len(v)
1236 title = "Fixed Variables"
1237 text += "\n"
1238 if len(v):
1239 for var in v:
1240 text += "\n%s\t= %f"%(str(var),var.getValue())
1241 else:
1242 text += "\nnone"
1243 _dialog = InfoDialog(self,self.window,text,title,tabs=[100,200])
1244 _dialog.run()
1245
1246 def on_show_freeable_variables_activate(self,*args):
1247 try:
1248 v = self.sim.getFreeableVariables()
1249 except RuntimeError,e:
1250 self.reporter.reportError("Unable to show freeable variables: %s"%str(e))
1251 return
1252 text = "Freeable Variables"
1253 title = text
1254 text += "\n"
1255 if len(v):
1256 for var in v:
1257 text += "\n%s" % var
1258 else:
1259 text += "\nnone"
1260 _dialog = InfoDialog(self,self.window,text,title)
1261 _dialog.run()
1262
1263 def on_show_external_functions_activate(self,*args):
1264 v = self.library.getExtMethods()
1265 text = "External Functions"
1266 title = text
1267 text +="\nHere is the list of external functions currently present in"
1268 text +=" the Library:"
1269
1270 if len(v):
1271 for ext in v:
1272 text += "\n\n%s (%d inputs, %d outputs):" % \
1273 (ext.getName(), ext.getNumInputs(), ext.getNumOutputs())
1274 text += "\n%s" % ext.getHelp()
1275 else:
1276 text +="\n\nNone"
1277 _dialog = InfoDialog(self,self.window,text,title)
1278 _dialog.run()
1279
1280 def on_notes_view_activate(self,*args):
1281 t = None
1282 try:
1283 D = self.library.getAnnotationDatabase()
1284 i = self.modelview.get_selected_instance()
1285 if i and i.isModel():
1286 t = i.getType()
1287 else:
1288 self.reporter.reportError("First select a MODEL instance");
1289 return
1290 v = D.getNotes(t)
1291 except RuntimeError,e:
1292 self.reporter.reportError("Unable to show notes: %s"%str(e))
1293 return
1294 text = "Notes for '%s'" % t.getName()
1295 title = text
1296 text += "\nHere are all notes defined within this MODEL:"
1297 nn = {}
1298 if len(v):
1299 for n in v:
1300 text += "\n\n%s (%s):" % (n.getId(), n.getLanguage())
1301 text += "\n\t%s" % n.getText()
1302 else:
1303 text += "\n\nThere are no noted defined locally within in this model"
1304
1305 _dialog = InfoDialog(self,self.window,text,title)
1306 _dialog.run()
1307
1308 def on_maintabs_switch_page(self,notebook,page,pagenum):
1309 #print("Page switched to %d" % pagenum)
1310 if pagenum in self.tabs.keys():
1311 self.currentobservertab = pagenum
1312
1313 def create_observer(self,name=None):
1314 _xml = gtk.glade.XML(self.glade_file,"observervbox");
1315 _label = gtk.Label();
1316 _tab = self.maintabs.append_page(_xml.get_widget("observervbox"),_label);
1317 _obs = ObserverTab(xml=_xml, name=name, browser=self, tab=_tab)
1318 _label.set_text(_obs.name)
1319 self.observers.append(_obs)
1320 self.tabs[_tab] = _obs
1321 self.currentobservertab = _tab
1322 return _obs
1323
1324 def sync_observers(self):
1325 for _o in self.observers:
1326 _o.sync()
1327
1328 def delete_event(self, widget, event):
1329 self.do_quit()
1330 return False
1331
1332 def observe(self,instance):
1333 if len(self.observers) ==0:
1334 self.create_observer()
1335 _observer = self.tabs[self.currentobservertab]
1336 _observer.add_instance(instance)
1337
1338 if __name__ == "__main__":
1339 b = Browser();
1340 b.run()

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