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

Annotation of /trunk/pygtk/diagnose.py

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2074 - (hide annotations) (download) (as text)
Fri Sep 4 06:50:08 2009 UTC (9 years, 1 month ago) by arijit
File MIME type: text/x-python
File size: 13986 byte(s)
Google SoC 2009 Project : Implementation of canvas based modeller for energy systems
1 johnpye 280 import gtk
2     import gtk.glade
3 johnpye 463 import ascpy
4 johnpye 280 from itertools import groupby
5     from operator import itemgetter
6 johnpye 283 import math
7 johnpye 284 import re
8 johnpye 280
9 johnpye 351 import config
10 johnpye 735 from infodialog import *
11 johnpye 351
12 johnpye 284 ZOOM_RE = re.compile(r"([0-9]+)\s*%?")
13 johnpye 895 MAX_ZOOM_SIZE = float(2000) # float
14     MAX_ZOOM_RATIO = float(16) # float
15 johnpye 287 AT_BOUND_TOL = 0.0001;
16 johnpye 284
17 johnpye 280 class DiagnoseWindow:
18 johnpye 351 def __init__(self,browser,block=0):
19 johnpye 280 self.browser=browser
20 johnpye 437 _xml = gtk.glade.XML(browser.glade_file,"diagnosewin")
21 johnpye 280 _xml.signal_autoconnect(self)
22    
23     self.window = _xml.get_widget("diagnosewin")
24 johnpye 328 self.window.set_transient_for(self.browser.window)
25    
26 johnpye 533 try:
27     _icon = gtk.Image()
28     _iconpath = browser.assets_dir+'diagnose'+config.ICON_EXTENSION
29     print "ICON PATH =",_iconpath
30     _icon.set_from_file(_iconpath)
31     print "ICON = ",_icon
32     self.window.set_icon(_icon)
33     except:
34     pass
35 johnpye 455
36 johnpye 284 self.imagescroll = _xml.get_widget("imagescroll")
37 johnpye 282 self.image = _xml.get_widget("image")
38 johnpye 280 self.blockentry = _xml.get_widget("blockentry")
39 johnpye 284 self.zoomentry = _xml.get_widget("zoomentry")
40 johnpye 280
41 johnpye 736 self.var = None; self.rel = None
42 jpye 2042 self.varname = _xml.get_widget("varname1")
43 johnpye 736 self.varval = _xml.get_widget("varval")
44     self.varinfobutton = _xml.get_widget("varinfobutton")
45 jpye 2042 self.relname = _xml.get_widget("relname1")
46 johnpye 736 self.relresid = _xml.get_widget("relresid")
47 johnpye 735 self.relinfobutton = _xml.get_widget("relinfobutton")
48 johnpye 286
49 johnpye 280 self.varview = _xml.get_widget("varview")
50     self.varbuf = gtk.TextBuffer()
51     self.varview.set_buffer(self.varbuf)
52     self.varcollapsed = _xml.get_widget("varcollapsed")
53     self.relview = _xml.get_widget("relview")
54     self.relcollapsed = _xml.get_widget("relcollapsed")
55     self.relvalues = _xml.get_widget("relvalues")
56     self.rellabels = _xml.get_widget("rellabels")
57     self.relrels = _xml.get_widget("relrels")
58     self.relresids = _xml.get_widget("relresids")
59     self.relbuf = gtk.TextBuffer()
60     self.relview.set_buffer(self.relbuf)
61    
62 johnpye 294 self.im = None
63 johnpye 285 self.block = 0
64 johnpye 294 self.apply_prefs()
65    
66 johnpye 280 self.prepare_data()
67 johnpye 285 self.fill_values(block) # block zero
68 johnpye 280
69     def run(self):
70     self.window.run()
71     self.window.hide()
72    
73 johnpye 294 def apply_prefs(self):
74 johnpye 319 vc = self.browser.prefs.getBoolPref("Diagnose","varcollapsed",True)
75    
76 johnpye 294 print "VARCOLLAPSED =",vc
77     self.varcollapsed.set_active(vc)
78 johnpye 319 self.relcollapsed.set_active(self.browser.prefs.getBoolPref("Diagnose","relcollapsed",True))
79 johnpye 294
80 johnpye 280 def prepare_data(self):
81     # convert incidence map to pylab numarray type:
82 arijit 2074 print "PREPARING DATA to be loaded"
83 johnpye 280 self.im = self.browser.sim.getIncidenceMatrix()
84     self.data = self.im.getIncidenceData()
85     print "DATA LOADED"
86    
87 johnpye 284 self.zoom=1;
88 johnpye 280
89     def fill_values(self, block):
90 johnpye 319
91 johnpye 283 try:
92 johnpye 736 if self.im.getNumBlocks()==0:
93     print "NO BLOCKS!"
94     self.image.set_from_stock(gtk.STOCK_DIALOG_ERROR
95     ,gtk.ICON_SIZE_DIALOG
96     )
97     self.browser.reporter.reportError(
98     "Can't 'Diagnose blocks' until solver has been used."
99     )
100     return;
101 johnpye 283 rl,cl,rh,ch = self.im.getBlockLocation(block)
102     except IndexError:
103 johnpye 319 if block >= self.im.getNumBlocks():
104     block = self.im.getNumBlocks() - 1
105     rl,cl,rh,ch = self.im.getBlockLocation(block)
106     else:
107     print "BLOCK INDEX ERROR: block =",block
108     self.blockentry.set_text(str(self.block))
109     return
110     except RuntimeError,e:
111     print "ERROR GETTING BLOCK LOCATION:",str(e)
112 johnpye 285 self.blockentry.set_text(str(self.block))
113 johnpye 283 return
114 johnpye 285
115 johnpye 280 self.block = block
116     self.blockentry.set_text(str(block))
117 johnpye 283
118 johnpye 286 self.rl = rl
119     self.cl = cl
120     self.rh = rh
121     self.ch = ch
122    
123 johnpye 283 nr = int(rh-rl+1);
124     nc = int(ch-cl+1);
125    
126 johnpye 669 print "STARTING IMAGE CREATION"
127 johnpye 282 # refer http://pygtk.org/pygtk2tutorial/sec-DrawingMethods.html
128     c = chr(255)
129 johnpye 283 b = nr*nc*3*[c]
130     rowstride = 3 * nc
131    
132     blackdot = [chr(0)]*3;
133     reddot = [chr(255), chr(0), chr(0)]
134     pinkdot = [chr(255), chr(127), chr(127)]
135     skydot = [chr(127), chr(127), chr(255)]
136     bluedot = [chr(0), chr(0), chr(255)]
137 johnpye 285 hotpinkdot = [chr(255), chr(47), chr(179)] # very big (+/-)
138     brightbluedot = [chr(71), chr(157), chr(255)] # very small (+/-)
139     greendot = [chr(87), chr(193), chr(70)] # close to 1
140     orangedot = [chr(255), chr(207), chr(61)] # 10-1000
141     bluegreendot = [chr(70), chr(221), chr(181)] # 0.001 - 0.1
142 johnpye 280 for i in self.data:
143 johnpye 283 if i.row < rl or i.row > rh or i.col < cl or i.col > ch:
144     continue
145     r = i.row - rl;
146     c = i.col - cl;
147     pos = rowstride*r + 3*c
148     dot = blackdot;
149     var = self.im.getVariable(i.col);
150 johnpye 287 if abs( (var.getValue()-var.getUpperBound())/ var.getNominal() ) < AT_BOUND_TOL:
151     dot = reddot
152     elif abs( var.getValue() - var.getLowerBound() ) / var.getNominal() < AT_BOUND_TOL:
153     dot = reddot
154     else:
155     rat = var.getValue() / var.getNominal()
156     if rat!=0:
157     try:
158     val = abs(rat)
159     if abs(rat) > 1000:
160     dot = hotpinkdot
161     elif abs(rat) > 10:
162     dot = orangedot
163     elif abs(rat) < 0.001:
164     dot = brightbluedot
165     elif abs(rat) < 10 and abs(rat) > 0.1:
166     dot = greendot
167     elif abs(rat) > 0.001 and abs(rat) < 0.1:
168     dot = bluegreendot
169     else:
170     dot = blackdot
171     except ValueError, e:
172     pass
173 johnpye 284 #print "DOT: ",dot
174 johnpye 283 b[pos], b[pos+1], b[pos+2] = dot
175    
176 johnpye 282 d = ''.join(b)
177 johnpye 283
178 johnpye 669 print "DONE IMAGE CREATION"
179 johnpye 282
180 johnpye 284 self.pixbuf = gtk.gdk.pixbuf_new_from_data(d, gtk.gdk.COLORSPACE_RGB, False, 8 \
181     , nc, nr, rowstride);
182 johnpye 283
183 johnpye 284 self.nr = nr
184     self.nc = nc
185     self.zoom = -1 # to fit, up to max 16x
186     self.do_zoom()
187 johnpye 283
188 johnpye 669 print "DONE IMAGE TRANSFER TO SERVER"
189 johnpye 283
190 johnpye 284 self.fill_var_names()
191     self.fill_rel_names()
192 johnpye 286
193 johnpye 735 self.fill_selection_info()
194 johnpye 280
195 johnpye 669 print "DONE FILL VALUES"
196 johnpye 286
197 johnpye 735 def fill_selection_info(self):
198     if self.var:
199 jose 2071 #self.varname.set_text(self.var.getName())
200 johnpye 735 self.varval.set_text(str(self.var.getValue()))
201     self.varinfobutton.set_sensitive(True)
202     else:
203     self.varname.set_text("")
204     self.varval.set_text("")
205     self.varinfobutton.set_sensitive(False)
206    
207     if self.rel:
208     self.relname.set_text(self.rel.getName())
209     self.relresid.set_text(str(self.rel.getResidual()))
210     self.relinfobutton.set_sensitive(True)
211     else:
212     self.relname.set_text("")
213     self.relresid.set_text("")
214     self.relinfobutton.set_sensitive(False)
215    
216 johnpye 284 def do_zoom(self):
217     if self.zoom == -1:
218     w, h = self.imagescroll.size_request()
219     #print "SCALE TO FIX, w=%d, h=%d" % (w,h)
220     if self.nc/self.nr > w/h:
221     # a 'wide' image
222 johnpye 895 self.zoom = float(w) / self.nc
223 johnpye 284 else:
224 johnpye 895 self.zoom = float(h) / self.nr
225 johnpye 283
226 johnpye 1109 #self.browser.reporter.reportNote("Diagnose window: preliminary calculated zoom = %f (nr = %d, nc = %d)" % (self.zoom, self.nr, self.nc))
227 johnpye 895
228    
229 johnpye 284 if self.zoom > MAX_ZOOM_RATIO:
230     self.zoom = MAX_ZOOM_RATIO
231 johnpye 280
232 johnpye 284 if self.zoom * self.nc > MAX_ZOOM_SIZE or self.zoom * self.nr > MAX_ZOOM_SIZE:
233 jpye 2053 self.browser.reporter.reportNote("image is too big, reducing to MAX_ZOOM_SIZE = %f" % MAX_ZOOM_SIZE);
234 johnpye 284 self.zoom = MAX_ZOOM_SIZE / max(self.nc,self.nr)
235 johnpye 283
236 johnpye 1109 #self.browser.reporter.reportNote("Diagnose window: matrix zoom = %f" % self.zoom)
237 johnpye 284 w = int(self.zoom * self.nc);
238     h = int(self.zoom * self.nr);
239    
240     self.zoomentry.set_text("%d %%" % (int(self.zoom*100)) )
241 johnpye 280
242 johnpye 284 if self.zoom < 2:
243     pb1 = self.pixbuf.scale_simple(w,h,gtk.gdk.INTERP_BILINEAR)
244     else:
245     pb1 = self.pixbuf.scale_simple(w,h,gtk.gdk.INTERP_NEAREST)
246    
247     self.image.set_from_pixbuf(pb1)
248    
249 johnpye 280 def fill_var_names(self):
250 johnpye 669 print "FILL VAR NAMES"
251    
252 johnpye 280 names = [str(i) for i in self.im.getBlockVars(self.block)]
253 johnpye 669
254 johnpye 895 #print "NAMES:",names
255 johnpye 669
256 johnpye 280 if self.varcollapsed.get_active():
257 johnpye 287 res = reduce(names)
258 johnpye 280 rows = []
259     for k in res:
260     if k=="":
261     for r in res[k]:
262     rows.append(r)
263     else:
264     rows.append( '%s:\n\t%s' % (k, "\n\t".join(res[k])) )
265     text = "\n".join(rows)
266     else:
267     text = "\n".join(names)
268     self.varbuf.set_text(text)
269    
270 johnpye 669 print "DONE VAR NAMES"
271    
272 johnpye 280 def fill_rel_names(self):
273 johnpye 669 print "REL NAMES"
274    
275     rels = self.im.getBlockRels(self.block)
276    
277     print "GOT RELS, NOW GETTING NAMES"
278    
279     names = [str(i) for i in rels]
280    
281 johnpye 895 #print "NAMES =",names
282 johnpye 669
283 johnpye 280 if self.relcollapsed.get_active():
284 johnpye 287 res = reduce(names)
285     rows = []
286     for k in res:
287     if k=="":
288     for r in res[k]:
289     rows.append(r)
290     else:
291     rows.append( '%s:\n\t%s' % (k, "\n\t".join(res[k])) )
292     text = "\n".join(rows)
293 johnpye 280 else:
294     text = "\n".join(names)
295     self.relbuf.set_text(text)
296    
297 johnpye 669 print "DONE REL NAMES"
298    
299 johnpye 280 def set_block(self, block):
300     self.fill_values(block)
301    
302 johnpye 284 def set_zoom(self,zoom):
303     self.zoom = zoom
304     self.do_zoom()
305    
306 johnpye 286 def show_cursor(self,x,y):
307     c = self.cl + int(x/self.zoom)
308     r = self.rl + int(y / self.zoom)
309     if c > self.ch or r > self.rh:
310     #print "OUT OF RANGE"
311     return
312 johnpye 735 self.var = self.im.getVariable(c)
313     self.rel = self.im.getRelation(r)
314     self.fill_selection_info()
315 johnpye 286
316     # GUI EVENT HOOKS-----------------------------------------------------------
317    
318 johnpye 735 def on_diagnosewin_close(self,*args):
319     self.window.response(gtk.RESPONSE_CLOSE);
320    
321     # incidence data view
322    
323 johnpye 280 def on_varcollapsed_toggled(self,*args):
324 johnpye 294 vc = self.varcollapsed.get_active()
325     self.browser.prefs.setBoolPref("Diagnose","varcollapsed",vc)
326     if self.im:
327     self.fill_var_names()
328 johnpye 280
329     def on_relcollapsed_toggled(self,*args):
330 johnpye 294 rc = self.varcollapsed.get_active()
331     self.browser.prefs.setBoolPref("Diagnose","relcollapsed",rc)
332     if self.im:
333     self.fill_rel_names()
334 johnpye 280
335 johnpye 735 # detailed information about vars and rels (solver-side information!)
336    
337     def on_varinfobutton_clicked(self,*args):
338     title = "Variable '%s'" % self.var
339     text = "%s\n%s\n" % (title,"(from the solver's view)")
340 johnpye 736
341     _rows = {
342     "Value": self.var.getValue()
343     ,"Nominal": self.var.getNominal()
344     ,"Lower bound": self.var.getLowerBound()
345     ,"Upper bound": self.var.getUpperBound()
346     }
347     for k,v in _rows.iteritems():
348 johnpye 737 text += "\n %s\t%s" % (k,value_human(v))
349 johnpye 735
350 johnpye 737 text += "\n\nIncident with %d relations:" % self.var.getNumIncidentRelations()
351 johnpye 735 for r in self.var.getIncidentRelations():
352 johnpye 736 text += "\n %s" % r.getName()
353 johnpye 735
354 johnpye 737 _dialog = InfoDialog(self.browser,self.window,text,title,tabs=(150,300))
355 johnpye 735 _dialog.run()
356    
357     def on_relinfobutton_clicked(self,*args):
358     title = "Relation '%s'" % self.rel
359     text = "%s\n%s\n" % (title,"(from the solver's view)")
360 johnpye 737 text += "\n %s\t%15f" % ("Residual", self.rel.getResidual())
361 johnpye 735
362 johnpye 736 text += "\n\nRelation expression:\n"
363     text += self.rel.getRelationAsString()
364    
365 johnpye 737 text += "\n\nIncident with %d variables:" % self.rel.getNumIncidentVariables()
366     for v in self.rel.getIncidentVariables():
367     text += "\n %s\t= %s" % ( v.getName(),value_human(v.getValue()) )
368    
369     _dialog = InfoDialog(self.browser,self.window,text,title,tabs=(150,300))
370 johnpye 735 _dialog.run()
371    
372    
373     # block navigation
374    
375 johnpye 280 def on_nextbutton_clicked(self,*args):
376     self.set_block(self.block + 1)
377    
378     def on_prevbutton_clicked(self,*args):
379 johnpye 290 self.set_block(self.block - 1)
380 johnpye 280
381 johnpye 290 def on_prevbigbutton_clicked(self,*args):
382     b = self.block - 1
383 johnpye 291 while b >= 0:
384 johnpye 290 rl,cl,rh,ch = self.im.getBlockLocation(b)
385     if rh-rl > 0 or ch-cl>0:
386     self.set_block(b)
387     b = b - 1
388     print "NO PRECEDING 'BIG' BLOCKS"
389    
390     def on_nextbigbutton_clicked(self,*args):
391     b = self.block + 1
392     n = self.im.getNumBlocks()
393     while b < n:
394     rl,cl,rh,ch = self.im.getBlockLocation(b)
395     if rh-rl > 0 or ch-cl>0:
396     self.set_block(b)
397     b = b + 1
398     print "NO FOLLOWING 'BIG' BLOCKS"
399    
400 johnpye 283 def on_blockentry_key_press_event(self,widget,event):
401     keyname = gtk.gdk.keyval_name(event.keyval)
402     print "KEY ",keyname
403     if keyname=="Return":
404     self.set_block( int(self.blockentry.get_text()) )
405 johnpye 280
406 johnpye 735 # zoom in and out
407    
408 johnpye 284 def on_zoominbutton_clicked(self,*args):
409     z = int( math.log(self.zoom)/math.log(2) )
410     z = pow(2,z + 1);
411     self.set_zoom(z)
412    
413     def on_zoomoutbutton_clicked(self,*args):
414     z = int( math.log(self.zoom)/math.log(2) + 0.999)
415     z = pow(2,z - 1);
416     self.set_zoom(z)
417    
418     def on_zoomentry_key_press_event(self,widget,event):
419     keyname = gtk.gdk.keyval_name(event.keyval)
420     print "KEY ",keyname
421     if keyname=="Return":
422     t = self.zoomentry.get_text()
423     m = ZOOM_RE.match(t)
424     if not m:
425     self.zoomentry.set_text("%d %%" % int(self.zoom*100))
426     for mm in m:
427     print m
428     self.set_zoom( int(self.zoomentry.get_text()) )
429    
430 johnpye 735 # clicking in incidence matrix to get updated information at RHS
431    
432 johnpye 286 def on_imageevent_motion_notify_event(self,widget,event):
433     self.show_cursor(event.x, event.y)
434    
435     def on_imageevent_button_press_event(self,widget,event):
436     self.show_cursor(event.x, event.y)
437    
438    
439 johnpye 737 def value_human(v):
440     if v==0 or abs( math.log10(abs(v)) )<8:
441     return "%f" % v
442     return "%e" % v
443    
444     #---------------------------------------
445     # Procedures to 'fold' a list of items from a hierarchy
446 johnpye 280 # http://www.experts-exchange.com/Programming/Programming_Languages/Python/Q_21719649.html
447 johnpye 737 # It's still buggy, I think
448 johnpye 280
449     def fold(data):
450     """ fold sorted numeric sequence data into ranged representation:
451     >>> fold([1, 4,5,6, 10, 15,16,17,18, 22, 25,26,27,28])
452     '[1,4-6,10,15-18,22,25-28]'
453     """
454     folded = []
455 johnpye 287 for k, g in groupby(enumerate(sorted(data)), lambda (i,x):i-x):
456 johnpye 280 seq = map(itemgetter(1), g)
457     if len(seq) > 1:
458     x = '%s-%s' % (seq[0], seq[-1])
459     else:
460     x = str(seq[0])
461     folded.append(x)
462     return folded and '[%s]' % ','.join(folded) or ''
463    
464 johnpye 287 def reduce(names):
465     """reduce a list of items nto something more readable:
466 johnpye 280 >>> data = 'C.x C.p C.T C.delta[1] C.delta[2] C.delta[3] C.sat.x C.sat.p C.h C.delta[5]'.split()
467     >>> res = reduce(data)
468     >>> for k in sorted(res):
469     ... print '%s: %s' % (k, res[k])
470     C: T, delta[1-3,5], h, p, x
471     C.sat: p, x
472     """
473 johnpye 287 data = sorted([n.split('.') for n in sorted(names)], key=len)
474 johnpye 280 res = {}
475     for k, g in groupby(data, lambda x: len(x)):
476 johnpye 287 if k == 1:
477     indexed = {}
478 jpye 1430 seq = set([get(indexed, item) for item in g])
479 johnpye 287 res['[global]'] = [ i+fold(indexed.get(i, [])) for i in sorted(seq) ]
480     else:
481     for key, g1 in groupby(g, lambda x: '.'.join(x[:-1])):
482     indexed = {}
483     seq = set(get(indexed, item) for item in g1)
484     res[key] = [ i+fold(indexed.get(i, [])) for i in sorted(seq) ]
485 johnpye 280 return res
486    
487     def get(indexed, item):
488     item = item[-1]
489     if item.endswith(']'):
490     item, idx = item[:-1].split('[')
491     indexed.setdefault(item, []).append(int(idx))
492     return item
493 johnpye 737

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