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

Contents of /trunk/pygtk/gtkbrowser.py

Parent Directory Parent Directory | Revision Log Revision Log


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

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