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

Annotation of /trunk/pygtk/diagnose.py

Parent Directory Parent Directory | Revision Log Revision Log


Revision 533 - (hide annotations) (download) (as text)
Mon Apr 24 05:54:11 2006 UTC (13 years, 11 months ago) by johnpye
File MIME type: text/x-python
File size: 10908 byte(s)
Starting to refactor the model browser as its own python class.
Fixed a bug with the 'diagnose' feature on linux due to failed loading of an icon.
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    
11 johnpye 284 ZOOM_RE = re.compile(r"([0-9]+)\s*%?")
12     MAX_ZOOM_SIZE = 2000
13     MAX_ZOOM_RATIO = 16
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 johnpye 437 _xml = gtk.glade.XML(browser.glade_file,"diagnosewin")
20 johnpye 280 _xml.signal_autoconnect(self)
21    
22     self.window = _xml.get_widget("diagnosewin")
23 johnpye 328 self.window.set_transient_for(self.browser.window)
24    
25 johnpye 533 try:
26     _icon = gtk.Image()
27     _iconpath = browser.assets_dir+'diagnose'+config.ICON_EXTENSION
28     print "ICON PATH =",_iconpath
29     _icon.set_from_file(_iconpath)
30     print "ICON = ",_icon
31     self.window.set_icon(_icon)
32     except:
33     pass
34 johnpye 455
35 johnpye 284 self.imagescroll = _xml.get_widget("imagescroll")
36 johnpye 282 self.image = _xml.get_widget("image")
37 johnpye 280 self.blockentry = _xml.get_widget("blockentry")
38 johnpye 284 self.zoomentry = _xml.get_widget("zoomentry")
39 johnpye 280
40 johnpye 286 self.varname = _xml.get_widget("varname");
41     self.varval = _xml.get_widget("varval");
42     self.relname = _xml.get_widget("relname");
43     self.relresid = _xml.get_widget("relresid");
44    
45 johnpye 280 self.varview = _xml.get_widget("varview")
46     self.varbuf = gtk.TextBuffer()
47     self.varview.set_buffer(self.varbuf)
48     self.varcollapsed = _xml.get_widget("varcollapsed")
49     self.relview = _xml.get_widget("relview")
50     self.relcollapsed = _xml.get_widget("relcollapsed")
51     self.relvalues = _xml.get_widget("relvalues")
52     self.rellabels = _xml.get_widget("rellabels")
53     self.relrels = _xml.get_widget("relrels")
54     self.relresids = _xml.get_widget("relresids")
55     self.relbuf = gtk.TextBuffer()
56     self.relview.set_buffer(self.relbuf)
57    
58 johnpye 294 self.im = None
59 johnpye 285 self.block = 0
60 johnpye 294 self.apply_prefs()
61    
62 johnpye 280 self.prepare_data()
63 johnpye 285 self.fill_values(block) # block zero
64 johnpye 280
65     def run(self):
66     self.window.run()
67     self.window.hide()
68    
69 johnpye 294 def apply_prefs(self):
70 johnpye 319 vc = self.browser.prefs.getBoolPref("Diagnose","varcollapsed",True)
71    
72 johnpye 294 print "VARCOLLAPSED =",vc
73     self.varcollapsed.set_active(vc)
74 johnpye 319 self.relcollapsed.set_active(self.browser.prefs.getBoolPref("Diagnose","relcollapsed",True))
75 johnpye 294
76 johnpye 280 def prepare_data(self):
77     # convert incidence map to pylab numarray type:
78     print "PREPARING DATA"
79     self.im = self.browser.sim.getIncidenceMatrix()
80     self.data = self.im.getIncidenceData()
81     print "DATA LOADED"
82    
83 johnpye 284 self.zoom=1;
84 johnpye 280
85     def fill_values(self, block):
86 johnpye 319
87 johnpye 283 try:
88     rl,cl,rh,ch = self.im.getBlockLocation(block)
89     except IndexError:
90 johnpye 319 if block >= self.im.getNumBlocks():
91     block = self.im.getNumBlocks() - 1
92     rl,cl,rh,ch = self.im.getBlockLocation(block)
93     else:
94     print "BLOCK INDEX ERROR: block =",block
95     self.blockentry.set_text(str(self.block))
96     return
97     except RuntimeError,e:
98     print "ERROR GETTING BLOCK LOCATION:",str(e)
99 johnpye 285 self.blockentry.set_text(str(self.block))
100 johnpye 283 return
101 johnpye 285
102 johnpye 280 self.block = block
103     self.blockentry.set_text(str(block))
104 johnpye 283
105 johnpye 286 self.rl = rl
106     self.cl = cl
107     self.rh = rh
108     self.ch = ch
109    
110 johnpye 283 nr = int(rh-rl+1);
111     nc = int(ch-cl+1);
112    
113 johnpye 284 #print "STARTING IMAGE CREATION"
114 johnpye 282 # refer http://pygtk.org/pygtk2tutorial/sec-DrawingMethods.html
115     c = chr(255)
116 johnpye 283 b = nr*nc*3*[c]
117     rowstride = 3 * nc
118    
119     blackdot = [chr(0)]*3;
120     reddot = [chr(255), chr(0), chr(0)]
121     pinkdot = [chr(255), chr(127), chr(127)]
122     skydot = [chr(127), chr(127), chr(255)]
123     bluedot = [chr(0), chr(0), chr(255)]
124 johnpye 285 hotpinkdot = [chr(255), chr(47), chr(179)] # very big (+/-)
125     brightbluedot = [chr(71), chr(157), chr(255)] # very small (+/-)
126     greendot = [chr(87), chr(193), chr(70)] # close to 1
127     orangedot = [chr(255), chr(207), chr(61)] # 10-1000
128     bluegreendot = [chr(70), chr(221), chr(181)] # 0.001 - 0.1
129 johnpye 280 for i in self.data:
130 johnpye 283 if i.row < rl or i.row > rh or i.col < cl or i.col > ch:
131     continue
132     r = i.row - rl;
133     c = i.col - cl;
134     pos = rowstride*r + 3*c
135     dot = blackdot;
136     var = self.im.getVariable(i.col);
137 johnpye 287 if abs( (var.getValue()-var.getUpperBound())/ var.getNominal() ) < AT_BOUND_TOL:
138     dot = reddot
139     elif abs( var.getValue() - var.getLowerBound() ) / var.getNominal() < AT_BOUND_TOL:
140     dot = reddot
141     else:
142     rat = var.getValue() / var.getNominal()
143     if rat!=0:
144     try:
145     val = abs(rat)
146     if abs(rat) > 1000:
147     dot = hotpinkdot
148     elif abs(rat) > 10:
149     dot = orangedot
150     elif abs(rat) < 0.001:
151     dot = brightbluedot
152     elif abs(rat) < 10 and abs(rat) > 0.1:
153     dot = greendot
154     elif abs(rat) > 0.001 and abs(rat) < 0.1:
155     dot = bluegreendot
156     else:
157     dot = blackdot
158     except ValueError, e:
159     pass
160 johnpye 284 #print "DOT: ",dot
161 johnpye 283 b[pos], b[pos+1], b[pos+2] = dot
162    
163 johnpye 282 d = ''.join(b)
164 johnpye 283
165 johnpye 284 #print "DONE IMAGE CREATION"
166 johnpye 282
167 johnpye 284 self.pixbuf = gtk.gdk.pixbuf_new_from_data(d, gtk.gdk.COLORSPACE_RGB, False, 8 \
168     , nc, nr, rowstride);
169 johnpye 283
170 johnpye 284 self.nr = nr
171     self.nc = nc
172     self.zoom = -1 # to fit, up to max 16x
173     self.do_zoom()
174 johnpye 283
175 johnpye 284 #print "DONE IMAGE TRANSFER TO SERVER"
176 johnpye 283
177 johnpye 284 self.fill_var_names()
178     self.fill_rel_names()
179 johnpye 286
180     self.varname.set_text("");
181     self.varval.set_text("");
182     self.relname.set_text("");
183     self.relresid.set_text("");
184 johnpye 280
185 johnpye 286
186 johnpye 284 def do_zoom(self):
187     if self.zoom == -1:
188     w, h = self.imagescroll.size_request()
189     #print "SCALE TO FIX, w=%d, h=%d" % (w,h)
190     if self.nc/self.nr > w/h:
191     # a 'wide' image
192     self.zoom = w / self.nc
193     else:
194     self.zoom = h / self.nr
195 johnpye 283
196 johnpye 284 if self.zoom > MAX_ZOOM_RATIO:
197     self.zoom = MAX_ZOOM_RATIO
198 johnpye 280
199 johnpye 284 if self.zoom * self.nc > MAX_ZOOM_SIZE or self.zoom * self.nr > MAX_ZOOM_SIZE:
200     self.zoom = MAX_ZOOM_SIZE / max(self.nc,self.nr)
201 johnpye 283
202 johnpye 284 w = int(self.zoom * self.nc);
203     h = int(self.zoom * self.nr);
204    
205     self.zoomentry.set_text("%d %%" % (int(self.zoom*100)) )
206 johnpye 280
207 johnpye 284 if self.zoom < 2:
208     pb1 = self.pixbuf.scale_simple(w,h,gtk.gdk.INTERP_BILINEAR)
209     else:
210     pb1 = self.pixbuf.scale_simple(w,h,gtk.gdk.INTERP_NEAREST)
211    
212     self.image.set_from_pixbuf(pb1)
213    
214 johnpye 280 def fill_var_names(self):
215     names = [str(i) for i in self.im.getBlockVars(self.block)]
216     if self.varcollapsed.get_active():
217 johnpye 287 res = reduce(names)
218 johnpye 280 rows = []
219     for k in res:
220     if k=="":
221     for r in res[k]:
222     rows.append(r)
223     else:
224     rows.append( '%s:\n\t%s' % (k, "\n\t".join(res[k])) )
225     text = "\n".join(rows)
226     else:
227     text = "\n".join(names)
228     self.varbuf.set_text(text)
229    
230     def fill_rel_names(self):
231     names = [str(i) for i in self.im.getBlockRels(self.block)]
232     if self.relcollapsed.get_active():
233 johnpye 287 res = reduce(names)
234     rows = []
235     for k in res:
236     if k=="":
237     for r in res[k]:
238     rows.append(r)
239     else:
240     rows.append( '%s:\n\t%s' % (k, "\n\t".join(res[k])) )
241     text = "\n".join(rows)
242 johnpye 280 else:
243     text = "\n".join(names)
244     self.relbuf.set_text(text)
245    
246     def set_block(self, block):
247     self.fill_values(block)
248    
249 johnpye 284 def set_zoom(self,zoom):
250     self.zoom = zoom
251     self.do_zoom()
252    
253 johnpye 286 def show_cursor(self,x,y):
254     c = self.cl + int(x/self.zoom)
255     r = self.rl + int(y / self.zoom)
256     if c > self.ch or r > self.rh:
257     #print "OUT OF RANGE"
258     return
259     var = self.im.getVariable(c)
260     self.varname.set_text(var.getName())
261     self.varval.set_text(str(var.getValue()))
262     rel = self.im.getRelation(r)
263     self.relname.set_text(rel.getName())
264     self.relresid.set_text(str(rel.getResidual()))
265    
266     # GUI EVENT HOOKS-----------------------------------------------------------
267    
268 johnpye 280 def on_varcollapsed_toggled(self,*args):
269 johnpye 294 vc = self.varcollapsed.get_active()
270     self.browser.prefs.setBoolPref("Diagnose","varcollapsed",vc)
271     if self.im:
272     self.fill_var_names()
273 johnpye 280
274     def on_relcollapsed_toggled(self,*args):
275 johnpye 294 rc = self.varcollapsed.get_active()
276     self.browser.prefs.setBoolPref("Diagnose","relcollapsed",rc)
277     if self.im:
278     self.fill_rel_names()
279 johnpye 280
280     def on_nextbutton_clicked(self,*args):
281     self.set_block(self.block + 1)
282    
283     def on_prevbutton_clicked(self,*args):
284 johnpye 290 self.set_block(self.block - 1)
285 johnpye 280
286 johnpye 290 def on_prevbigbutton_clicked(self,*args):
287     b = self.block - 1
288 johnpye 291 while b >= 0:
289 johnpye 290 rl,cl,rh,ch = self.im.getBlockLocation(b)
290     if rh-rl > 0 or ch-cl>0:
291     self.set_block(b)
292     b = b - 1
293     print "NO PRECEDING 'BIG' BLOCKS"
294    
295     def on_nextbigbutton_clicked(self,*args):
296     b = self.block + 1
297     n = self.im.getNumBlocks()
298     while b < n:
299     rl,cl,rh,ch = self.im.getBlockLocation(b)
300     if rh-rl > 0 or ch-cl>0:
301     self.set_block(b)
302     b = b + 1
303     print "NO FOLLOWING 'BIG' BLOCKS"
304    
305 johnpye 283 def on_blockentry_key_press_event(self,widget,event):
306     keyname = gtk.gdk.keyval_name(event.keyval)
307     print "KEY ",keyname
308     if keyname=="Return":
309     self.set_block( int(self.blockentry.get_text()) )
310 johnpye 280
311 johnpye 284 def on_zoominbutton_clicked(self,*args):
312     z = int( math.log(self.zoom)/math.log(2) )
313     z = pow(2,z + 1);
314     self.set_zoom(z)
315    
316     def on_zoomoutbutton_clicked(self,*args):
317     z = int( math.log(self.zoom)/math.log(2) + 0.999)
318     z = pow(2,z - 1);
319     self.set_zoom(z)
320    
321     def on_zoomentry_key_press_event(self,widget,event):
322     keyname = gtk.gdk.keyval_name(event.keyval)
323     print "KEY ",keyname
324     if keyname=="Return":
325     t = self.zoomentry.get_text()
326     m = ZOOM_RE.match(t)
327     if not m:
328     self.zoomentry.set_text("%d %%" % int(self.zoom*100))
329     for mm in m:
330     print m
331     self.set_zoom( int(self.zoomentry.get_text()) )
332    
333 johnpye 286 def on_imageevent_motion_notify_event(self,widget,event):
334     self.show_cursor(event.x, event.y)
335    
336     def on_imageevent_button_press_event(self,widget,event):
337     self.show_cursor(event.x, event.y)
338    
339    
340 johnpye 280 # The following is from
341     # http://www.experts-exchange.com/Programming/Programming_Languages/Python/Q_21719649.html
342 johnpye 284 # it's still buggy.
343 johnpye 280
344     def fold(data):
345     """ fold sorted numeric sequence data into ranged representation:
346     >>> fold([1, 4,5,6, 10, 15,16,17,18, 22, 25,26,27,28])
347     '[1,4-6,10,15-18,22,25-28]'
348     """
349     folded = []
350 johnpye 287 for k, g in groupby(enumerate(sorted(data)), lambda (i,x):i-x):
351 johnpye 280 seq = map(itemgetter(1), g)
352     if len(seq) > 1:
353     x = '%s-%s' % (seq[0], seq[-1])
354     else:
355     x = str(seq[0])
356     folded.append(x)
357     return folded and '[%s]' % ','.join(folded) or ''
358    
359 johnpye 287 def reduce(names):
360     """reduce a list of items nto something more readable:
361 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()
362     >>> res = reduce(data)
363     >>> for k in sorted(res):
364     ... print '%s: %s' % (k, res[k])
365     C: T, delta[1-3,5], h, p, x
366     C.sat: p, x
367     """
368 johnpye 287 data = sorted([n.split('.') for n in sorted(names)], key=len)
369 johnpye 280 res = {}
370     for k, g in groupby(data, lambda x: len(x)):
371 johnpye 287 if k == 1:
372     indexed = {}
373     seq = set(get(indexed, item) for item in g)
374     res['[global]'] = [ i+fold(indexed.get(i, [])) for i in sorted(seq) ]
375     else:
376     for key, g1 in groupby(g, lambda x: '.'.join(x[:-1])):
377     indexed = {}
378     seq = set(get(indexed, item) for item in g1)
379     res[key] = [ i+fold(indexed.get(i, [])) for i in sorted(seq) ]
380 johnpye 280 return res
381    
382     def get(indexed, item):
383     item = item[-1]
384     if item.endswith(']'):
385     item, idx = item[:-1].split('[')
386     indexed.setdefault(item, []).append(int(idx))
387     return item

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