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

Annotation of /trunk/pygtk/diagnose.py

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2495 - (hide annotations) (download) (as text)
Tue Aug 16 11:35:08 2011 UTC (8 years, 1 month ago) by aakash
File MIME type: text/x-python
File size: 14819 byte(s)
Merge further changes from Aakash to trunk.
1 johnpye 280 import gtk
2 johnpye 463 import ascpy
3 johnpye 280 from itertools import groupby
4     from operator import itemgetter
5 johnpye 283 import math
6 johnpye 284 import re
7 johnpye 280
8 johnpye 351 import config
9 johnpye 735 from infodialog import *
10 johnpye 351
11 johnpye 284 ZOOM_RE = re.compile(r"([0-9]+)\s*%?")
12 johnpye 895 MAX_ZOOM_SIZE = float(2000) # float
13     MAX_ZOOM_RATIO = float(16) # float
14 johnpye 287 AT_BOUND_TOL = 0.0001;
15 johnpye 284
16 johnpye 280 class DiagnoseWindow:
17 johnpye 351 def __init__(self,browser,block=0):
18 johnpye 280 self.browser=browser
19 aakash 2494 self.browser.builder.add_objects_from_file(self.browser.glade_file, ["diagnosewin"])
20     self.browser.builder.connect_signals(self)
21     self.window = self.browser.builder.get_object("diagnosewin")
22 johnpye 328 self.window.set_transient_for(self.browser.window)
23    
24 johnpye 533 try:
25     _icon = gtk.Image()
26     _iconpath = browser.assets_dir+'diagnose'+config.ICON_EXTENSION
27     print "ICON PATH =",_iconpath
28     _icon.set_from_file(_iconpath)
29     print "ICON = ",_icon
30     self.window.set_icon(_icon)
31     except:
32     pass
33 johnpye 455
34 aakash 2494 self.blockstatus = self.browser.builder.get_object("blockstatustext")
35 jpye 2395
36 aakash 2494 self.imagescroll = self.browser.builder.get_object("imagescroll")
37     self.image = self.browser.builder.get_object("image")
38     self.blockentry = self.browser.builder.get_object("blockentry")
39     self.zoomentry = self.browser.builder.get_object("zoomentry")
40 johnpye 280
41 johnpye 736 self.var = None; self.rel = None
42 aakash 2494 self.varname = self.browser.builder.get_object("varname1")
43     self.varval = self.browser.builder.get_object("varval")
44     self.varinfobutton = self.browser.builder.get_object("varinfobutton")
45     self.relname = self.browser.builder.get_object("relname1")
46     self.relresid = self.browser.builder.get_object("relresid")
47     self.relinfobutton = self.browser.builder.get_object("relinfobutton")
48 johnpye 286
49 aakash 2494 self.varview = self.browser.builder.get_object("varview")
50 johnpye 280 self.varbuf = gtk.TextBuffer()
51     self.varview.set_buffer(self.varbuf)
52 aakash 2494 self.varcollapsed = self.browser.builder.get_object("varcollapsed")
53     self.relview = self.browser.builder.get_object("relview")
54     self.relcollapsed = self.browser.builder.get_object("relcollapsed")
55     self.relvalues = self.browser.builder.get_object("relvalues")
56     self.rellabels = self.browser.builder.get_object("rellabels")
57     self.relrels = self.browser.builder.get_object("relrels")
58     self.relresids = self.browser.builder.get_object("relresids")
59 johnpye 280 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 jpye 2395 self.fill_block_status()
193 johnpye 286
194 johnpye 735 self.fill_selection_info()
195 johnpye 280
196 johnpye 669 print "DONE FILL VALUES"
197 johnpye 286
198 johnpye 735 def fill_selection_info(self):
199     if self.var:
200 jpye 2238 self.varname.set_text(self.var.getName())
201 johnpye 735 self.varval.set_text(str(self.var.getValue()))
202     self.varinfobutton.set_sensitive(True)
203     else:
204     self.varname.set_text("")
205     self.varval.set_text("")
206     self.varinfobutton.set_sensitive(False)
207    
208     if self.rel:
209     self.relname.set_text(self.rel.getName())
210     self.relresid.set_text(str(self.rel.getResidual()))
211     self.relinfobutton.set_sensitive(True)
212     else:
213     self.relname.set_text("")
214     self.relresid.set_text("")
215     self.relinfobutton.set_sensitive(False)
216    
217 johnpye 284 def do_zoom(self):
218     if self.zoom == -1:
219     w, h = self.imagescroll.size_request()
220     #print "SCALE TO FIX, w=%d, h=%d" % (w,h)
221     if self.nc/self.nr > w/h:
222     # a 'wide' image
223 johnpye 895 self.zoom = float(w) / self.nc
224 johnpye 284 else:
225 johnpye 895 self.zoom = float(h) / self.nr
226 johnpye 283
227 johnpye 1109 #self.browser.reporter.reportNote("Diagnose window: preliminary calculated zoom = %f (nr = %d, nc = %d)" % (self.zoom, self.nr, self.nc))
228 johnpye 895
229    
230 johnpye 284 if self.zoom > MAX_ZOOM_RATIO:
231     self.zoom = MAX_ZOOM_RATIO
232 johnpye 280
233 johnpye 284 if self.zoom * self.nc > MAX_ZOOM_SIZE or self.zoom * self.nr > MAX_ZOOM_SIZE:
234 jpye 2053 self.browser.reporter.reportNote("image is too big, reducing to MAX_ZOOM_SIZE = %f" % MAX_ZOOM_SIZE);
235 johnpye 284 self.zoom = MAX_ZOOM_SIZE / max(self.nc,self.nr)
236 johnpye 283
237 johnpye 1109 #self.browser.reporter.reportNote("Diagnose window: matrix zoom = %f" % self.zoom)
238 johnpye 284 w = int(self.zoom * self.nc);
239     h = int(self.zoom * self.nr);
240    
241     self.zoomentry.set_text("%d %%" % (int(self.zoom*100)) )
242 johnpye 280
243 johnpye 284 if self.zoom < 2:
244     pb1 = self.pixbuf.scale_simple(w,h,gtk.gdk.INTERP_BILINEAR)
245     else:
246     pb1 = self.pixbuf.scale_simple(w,h,gtk.gdk.INTERP_NEAREST)
247    
248     self.image.set_from_pixbuf(pb1)
249    
250 jpye 2395 def fill_block_status(self):
251     print "FILL BLOCK STATUS"
252     s = self.im.getBlockStatus(self.block)
253     ss = "Failed"
254     if s == ascpy.IM_CONVERGED:
255     ss = "Converged"
256     elif s == ascpy.IM_NOT_YET_ATTEMPTED:
257     ss = "Not attempted yet"
258     elif s == ascpy.IM_OVER_TIME:
259     ss += " (time limit)"
260     elif s == ascpy.IM_OVER_ITER:
261     ss += " (iter limit)"
262     self.blockstatus.set_text(ss);
263    
264    
265 johnpye 280 def fill_var_names(self):
266 johnpye 669 print "FILL VAR NAMES"
267    
268 johnpye 280 names = [str(i) for i in self.im.getBlockVars(self.block)]
269 johnpye 669
270 johnpye 895 #print "NAMES:",names
271 johnpye 669
272 johnpye 280 if self.varcollapsed.get_active():
273 johnpye 287 res = reduce(names)
274 johnpye 280 rows = []
275     for k in res:
276     if k=="":
277     for r in res[k]:
278     rows.append(r)
279     else:
280     rows.append( '%s:\n\t%s' % (k, "\n\t".join(res[k])) )
281     text = "\n".join(rows)
282     else:
283     text = "\n".join(names)
284     self.varbuf.set_text(text)
285    
286 johnpye 669 print "DONE VAR NAMES"
287    
288 johnpye 280 def fill_rel_names(self):
289 johnpye 669 print "REL NAMES"
290    
291     rels = self.im.getBlockRels(self.block)
292    
293     print "GOT RELS, NOW GETTING NAMES"
294    
295     names = [str(i) for i in rels]
296    
297 johnpye 895 #print "NAMES =",names
298 johnpye 669
299 johnpye 280 if self.relcollapsed.get_active():
300 johnpye 287 res = reduce(names)
301     rows = []
302     for k in res:
303     if k=="":
304     for r in res[k]:
305     rows.append(r)
306     else:
307     rows.append( '%s:\n\t%s' % (k, "\n\t".join(res[k])) )
308     text = "\n".join(rows)
309 johnpye 280 else:
310     text = "\n".join(names)
311     self.relbuf.set_text(text)
312    
313 johnpye 669 print "DONE REL NAMES"
314    
315 johnpye 280 def set_block(self, block):
316     self.fill_values(block)
317    
318 johnpye 284 def set_zoom(self,zoom):
319     self.zoom = zoom
320     self.do_zoom()
321    
322 johnpye 286 def show_cursor(self,x,y):
323     c = self.cl + int(x/self.zoom)
324     r = self.rl + int(y / self.zoom)
325     if c > self.ch or r > self.rh:
326     #print "OUT OF RANGE"
327     return
328 johnpye 735 self.var = self.im.getVariable(c)
329     self.rel = self.im.getRelation(r)
330     self.fill_selection_info()
331 johnpye 286
332     # GUI EVENT HOOKS-----------------------------------------------------------
333    
334 johnpye 735 def on_diagnosewin_close(self,*args):
335     self.window.response(gtk.RESPONSE_CLOSE);
336    
337     # incidence data view
338    
339 johnpye 280 def on_varcollapsed_toggled(self,*args):
340 johnpye 294 vc = self.varcollapsed.get_active()
341     self.browser.prefs.setBoolPref("Diagnose","varcollapsed",vc)
342     if self.im:
343     self.fill_var_names()
344 johnpye 280
345     def on_relcollapsed_toggled(self,*args):
346 johnpye 294 rc = self.varcollapsed.get_active()
347     self.browser.prefs.setBoolPref("Diagnose","relcollapsed",rc)
348     if self.im:
349     self.fill_rel_names()
350 johnpye 280
351 johnpye 735 # detailed information about vars and rels (solver-side information!)
352    
353     def on_varinfobutton_clicked(self,*args):
354     title = "Variable '%s'" % self.var
355     text = "%s\n%s\n" % (title,"(from the solver's view)")
356 johnpye 736
357     _rows = {
358     "Value": self.var.getValue()
359     ,"Nominal": self.var.getNominal()
360     ,"Lower bound": self.var.getLowerBound()
361     ,"Upper bound": self.var.getUpperBound()
362     }
363     for k,v in _rows.iteritems():
364 johnpye 737 text += "\n %s\t%s" % (k,value_human(v))
365 johnpye 735
366 johnpye 737 text += "\n\nIncident with %d relations:" % self.var.getNumIncidentRelations()
367 johnpye 735 for r in self.var.getIncidentRelations():
368 johnpye 736 text += "\n %s" % r.getName()
369 johnpye 735
370 johnpye 737 _dialog = InfoDialog(self.browser,self.window,text,title,tabs=(150,300))
371 johnpye 735 _dialog.run()
372    
373     def on_relinfobutton_clicked(self,*args):
374     title = "Relation '%s'" % self.rel
375     text = "%s\n%s\n" % (title,"(from the solver's view)")
376 johnpye 737 text += "\n %s\t%15f" % ("Residual", self.rel.getResidual())
377 johnpye 735
378 johnpye 736 text += "\n\nRelation expression:\n"
379     text += self.rel.getRelationAsString()
380    
381 johnpye 737 text += "\n\nIncident with %d variables:" % self.rel.getNumIncidentVariables()
382     for v in self.rel.getIncidentVariables():
383     text += "\n %s\t= %s" % ( v.getName(),value_human(v.getValue()) )
384    
385     _dialog = InfoDialog(self.browser,self.window,text,title,tabs=(150,300))
386 johnpye 735 _dialog.run()
387    
388    
389     # block navigation
390    
391 johnpye 280 def on_nextbutton_clicked(self,*args):
392     self.set_block(self.block + 1)
393    
394     def on_prevbutton_clicked(self,*args):
395 johnpye 290 self.set_block(self.block - 1)
396 johnpye 280
397 johnpye 290 def on_prevbigbutton_clicked(self,*args):
398     b = self.block - 1
399 johnpye 291 while b >= 0:
400 johnpye 290 rl,cl,rh,ch = self.im.getBlockLocation(b)
401     if rh-rl > 0 or ch-cl>0:
402     self.set_block(b)
403 aakash 2495 return
404 johnpye 290 b = b - 1
405     print "NO PRECEDING 'BIG' BLOCKS"
406    
407     def on_nextbigbutton_clicked(self,*args):
408     b = self.block + 1
409     n = self.im.getNumBlocks()
410     while b < n:
411     rl,cl,rh,ch = self.im.getBlockLocation(b)
412     if rh-rl > 0 or ch-cl>0:
413     self.set_block(b)
414 aakash 2495 return
415 johnpye 290 b = b + 1
416     print "NO FOLLOWING 'BIG' BLOCKS"
417    
418 johnpye 283 def on_blockentry_key_press_event(self,widget,event):
419     keyname = gtk.gdk.keyval_name(event.keyval)
420     print "KEY ",keyname
421     if keyname=="Return":
422     self.set_block( int(self.blockentry.get_text()) )
423 johnpye 280
424 johnpye 735 # zoom in and out
425    
426 johnpye 284 def on_zoominbutton_clicked(self,*args):
427     z = int( math.log(self.zoom)/math.log(2) )
428     z = pow(2,z + 1);
429     self.set_zoom(z)
430    
431     def on_zoomoutbutton_clicked(self,*args):
432     z = int( math.log(self.zoom)/math.log(2) + 0.999)
433     z = pow(2,z - 1);
434     self.set_zoom(z)
435    
436     def on_zoomentry_key_press_event(self,widget,event):
437     keyname = gtk.gdk.keyval_name(event.keyval)
438     print "KEY ",keyname
439     if keyname=="Return":
440     t = self.zoomentry.get_text()
441     m = ZOOM_RE.match(t)
442     if not m:
443     self.zoomentry.set_text("%d %%" % int(self.zoom*100))
444     for mm in m:
445     print m
446     self.set_zoom( int(self.zoomentry.get_text()) )
447    
448 johnpye 735 # clicking in incidence matrix to get updated information at RHS
449    
450 johnpye 286 def on_imageevent_motion_notify_event(self,widget,event):
451     self.show_cursor(event.x, event.y)
452    
453     def on_imageevent_button_press_event(self,widget,event):
454     self.show_cursor(event.x, event.y)
455    
456    
457 johnpye 737 def value_human(v):
458     if v==0 or abs( math.log10(abs(v)) )<8:
459     return "%f" % v
460     return "%e" % v
461    
462     #---------------------------------------
463     # Procedures to 'fold' a list of items from a hierarchy
464 johnpye 280 # http://www.experts-exchange.com/Programming/Programming_Languages/Python/Q_21719649.html
465 johnpye 737 # It's still buggy, I think
466 johnpye 280
467     def fold(data):
468     """ fold sorted numeric sequence data into ranged representation:
469     >>> fold([1, 4,5,6, 10, 15,16,17,18, 22, 25,26,27,28])
470     '[1,4-6,10,15-18,22,25-28]'
471     """
472     folded = []
473 johnpye 287 for k, g in groupby(enumerate(sorted(data)), lambda (i,x):i-x):
474 johnpye 280 seq = map(itemgetter(1), g)
475     if len(seq) > 1:
476     x = '%s-%s' % (seq[0], seq[-1])
477     else:
478     x = str(seq[0])
479     folded.append(x)
480     return folded and '[%s]' % ','.join(folded) or ''
481    
482 johnpye 287 def reduce(names):
483     """reduce a list of items nto something more readable:
484 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()
485     >>> res = reduce(data)
486     >>> for k in sorted(res):
487     ... print '%s: %s' % (k, res[k])
488     C: T, delta[1-3,5], h, p, x
489     C.sat: p, x
490     """
491 johnpye 287 data = sorted([n.split('.') for n in sorted(names)], key=len)
492 johnpye 280 res = {}
493     for k, g in groupby(data, lambda x: len(x)):
494 johnpye 287 if k == 1:
495     indexed = {}
496 jpye 1430 seq = set([get(indexed, item) for item in g])
497 johnpye 287 res['[global]'] = [ i+fold(indexed.get(i, [])) for i in sorted(seq) ]
498     else:
499     for key, g1 in groupby(g, lambda x: '.'.join(x[:-1])):
500     indexed = {}
501     seq = set(get(indexed, item) for item in g1)
502     res[key] = [ i+fold(indexed.get(i, [])) for i in sorted(seq) ]
503 johnpye 280 return res
504    
505     def get(indexed, item):
506     item = item[-1]
507     if item.endswith(']'):
508     item, idx = item[:-1].split('[')
509     indexed.setdefault(item, []).append(int(idx))
510     return item
511 johnpye 737

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