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

Annotation of /trunk/pygtk/diagnose.py

Parent Directory Parent Directory | Revision Log Revision Log


Revision 895 - (hide annotations) (download) (as text)
Tue Oct 24 00:12:34 2006 UTC (13 years, 11 months ago) by johnpye
File MIME type: text/x-python
File size: 13966 byte(s)
Removed debug output (modelview.py)
Fixed bug in diagnose.py with large blocks
Removed debug output and improved error message in conopt.c
Removed debug output in lsode.c
Removed debup output in ascDynaload.c
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     self.varname = _xml.get_widget("varname")
43     self.varval = _xml.get_widget("varval")
44     self.varinfobutton = _xml.get_widget("varinfobutton")
45     self.relname = _xml.get_widget("relname")
46     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     print "PREPARING DATA"
83     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     self.varname.set_text(self.var.getName())
200     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 895 self.browser.reporter.reportNote("Diagnose window: preliminary calculated zoom = %f (nr = %d, nc = %d)" % (self.zoom, self.nr, self.nc))
227    
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 johnpye 895 self.browser.reporter.reportNode("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 895 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     seq = set(get(indexed, item) for item in g)
479     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