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

Annotation of /trunk/pygtk/diagnose.py

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3181 - (hide annotations) (download) (as text)
Tue Feb 7 05:11:24 2017 UTC (2 years, 9 months ago) by jpye
File MIME type: text/x-python
File size: 16550 byte(s)
make dependency on GTK optional, only if certain classes requested.

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

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