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

Contents of /trunk/pygtk/diagnose.py

Parent Directory Parent Directory | Revision Log Revision Log


Revision 669 - (show annotations) (download) (as text)
Wed Jun 21 07:00:45 2006 UTC (13 years, 2 months ago) by johnpye
File MIME type: text/x-python
File size: 11136 byte(s)
Merged changes from DAE branch (revisions 702 to 819) back into trunk.
This adds the Integration API to the ASCEND solver (in base/generic).
Also provides pre-alpha support for 'IDA' from the SUNDIALS suite, a DAE solver.
Many other minor code clean-ups, including adoption of new 'ASC_NEW' and friends (to replace 'ascmalloc')
Added some very sketchy stuff providing 'DIFF(...)' syntax, although it is anticipated that this will be removed.
1 import gtk
2 import gtk.glade
3 import ascpy
4 from itertools import groupby
5 from operator import itemgetter
6 import math
7 import re
8
9 import config
10
11 ZOOM_RE = re.compile(r"([0-9]+)\s*%?")
12 MAX_ZOOM_SIZE = 2000
13 MAX_ZOOM_RATIO = 16
14 AT_BOUND_TOL = 0.0001;
15
16 class DiagnoseWindow:
17 def __init__(self,browser,block=0):
18 self.browser=browser
19 _xml = gtk.glade.XML(browser.glade_file,"diagnosewin")
20 _xml.signal_autoconnect(self)
21
22 self.window = _xml.get_widget("diagnosewin")
23 self.window.set_transient_for(self.browser.window)
24
25 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
35 self.imagescroll = _xml.get_widget("imagescroll")
36 self.image = _xml.get_widget("image")
37 self.blockentry = _xml.get_widget("blockentry")
38 self.zoomentry = _xml.get_widget("zoomentry")
39
40 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 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 self.im = None
59 self.block = 0
60 self.apply_prefs()
61
62 self.prepare_data()
63 self.fill_values(block) # block zero
64
65 def run(self):
66 self.window.run()
67 self.window.hide()
68
69 def apply_prefs(self):
70 vc = self.browser.prefs.getBoolPref("Diagnose","varcollapsed",True)
71
72 print "VARCOLLAPSED =",vc
73 self.varcollapsed.set_active(vc)
74 self.relcollapsed.set_active(self.browser.prefs.getBoolPref("Diagnose","relcollapsed",True))
75
76 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 self.zoom=1;
84
85 def fill_values(self, block):
86
87 try:
88 rl,cl,rh,ch = self.im.getBlockLocation(block)
89 except IndexError:
90 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 self.blockentry.set_text(str(self.block))
100 return
101
102 self.block = block
103 self.blockentry.set_text(str(block))
104
105 self.rl = rl
106 self.cl = cl
107 self.rh = rh
108 self.ch = ch
109
110 nr = int(rh-rl+1);
111 nc = int(ch-cl+1);
112
113 print "STARTING IMAGE CREATION"
114 # refer http://pygtk.org/pygtk2tutorial/sec-DrawingMethods.html
115 c = chr(255)
116 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 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 for i in self.data:
130 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 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 #print "DOT: ",dot
161 b[pos], b[pos+1], b[pos+2] = dot
162
163 d = ''.join(b)
164
165 print "DONE IMAGE CREATION"
166
167 self.pixbuf = gtk.gdk.pixbuf_new_from_data(d, gtk.gdk.COLORSPACE_RGB, False, 8 \
168 , nc, nr, rowstride);
169
170 self.nr = nr
171 self.nc = nc
172 self.zoom = -1 # to fit, up to max 16x
173 self.do_zoom()
174
175 print "DONE IMAGE TRANSFER TO SERVER"
176
177 self.fill_var_names()
178 self.fill_rel_names()
179
180 self.varname.set_text("");
181 self.varval.set_text("");
182 self.relname.set_text("");
183 self.relresid.set_text("");
184
185 print "DONE FILL VALUES"
186
187 def do_zoom(self):
188 if self.zoom == -1:
189 w, h = self.imagescroll.size_request()
190 #print "SCALE TO FIX, w=%d, h=%d" % (w,h)
191 if self.nc/self.nr > w/h:
192 # a 'wide' image
193 self.zoom = w / self.nc
194 else:
195 self.zoom = h / self.nr
196
197 if self.zoom > MAX_ZOOM_RATIO:
198 self.zoom = MAX_ZOOM_RATIO
199
200 if self.zoom * self.nc > MAX_ZOOM_SIZE or self.zoom * self.nr > MAX_ZOOM_SIZE:
201 self.zoom = MAX_ZOOM_SIZE / max(self.nc,self.nr)
202
203 w = int(self.zoom * self.nc);
204 h = int(self.zoom * self.nr);
205
206 self.zoomentry.set_text("%d %%" % (int(self.zoom*100)) )
207
208 if self.zoom < 2:
209 pb1 = self.pixbuf.scale_simple(w,h,gtk.gdk.INTERP_BILINEAR)
210 else:
211 pb1 = self.pixbuf.scale_simple(w,h,gtk.gdk.INTERP_NEAREST)
212
213 self.image.set_from_pixbuf(pb1)
214
215 def fill_var_names(self):
216 print "FILL VAR NAMES"
217
218 names = [str(i) for i in self.im.getBlockVars(self.block)]
219
220 print "NAMES:",names
221
222 if self.varcollapsed.get_active():
223 res = reduce(names)
224 rows = []
225 for k in res:
226 if k=="":
227 for r in res[k]:
228 rows.append(r)
229 else:
230 rows.append( '%s:\n\t%s' % (k, "\n\t".join(res[k])) )
231 text = "\n".join(rows)
232 else:
233 text = "\n".join(names)
234 self.varbuf.set_text(text)
235
236 print "DONE VAR NAMES"
237
238 def fill_rel_names(self):
239 print "REL NAMES"
240
241 rels = self.im.getBlockRels(self.block)
242
243 print "GOT RELS, NOW GETTING NAMES"
244
245 names = [str(i) for i in rels]
246
247 print "NAMES =",names
248
249 if self.relcollapsed.get_active():
250 res = reduce(names)
251 rows = []
252 for k in res:
253 if k=="":
254 for r in res[k]:
255 rows.append(r)
256 else:
257 rows.append( '%s:\n\t%s' % (k, "\n\t".join(res[k])) )
258 text = "\n".join(rows)
259 else:
260 text = "\n".join(names)
261 self.relbuf.set_text(text)
262
263 print "DONE REL NAMES"
264
265 def set_block(self, block):
266 self.fill_values(block)
267
268 def set_zoom(self,zoom):
269 self.zoom = zoom
270 self.do_zoom()
271
272 def show_cursor(self,x,y):
273 c = self.cl + int(x/self.zoom)
274 r = self.rl + int(y / self.zoom)
275 if c > self.ch or r > self.rh:
276 #print "OUT OF RANGE"
277 return
278 var = self.im.getVariable(c)
279 self.varname.set_text(var.getName())
280 self.varval.set_text(str(var.getValue()))
281 rel = self.im.getRelation(r)
282 self.relname.set_text(rel.getName())
283 self.relresid.set_text(str(rel.getResidual()))
284
285 # GUI EVENT HOOKS-----------------------------------------------------------
286
287 def on_varcollapsed_toggled(self,*args):
288 vc = self.varcollapsed.get_active()
289 self.browser.prefs.setBoolPref("Diagnose","varcollapsed",vc)
290 if self.im:
291 self.fill_var_names()
292
293 def on_relcollapsed_toggled(self,*args):
294 rc = self.varcollapsed.get_active()
295 self.browser.prefs.setBoolPref("Diagnose","relcollapsed",rc)
296 if self.im:
297 self.fill_rel_names()
298
299 def on_nextbutton_clicked(self,*args):
300 self.set_block(self.block + 1)
301
302 def on_prevbutton_clicked(self,*args):
303 self.set_block(self.block - 1)
304
305 def on_prevbigbutton_clicked(self,*args):
306 b = self.block - 1
307 while b >= 0:
308 rl,cl,rh,ch = self.im.getBlockLocation(b)
309 if rh-rl > 0 or ch-cl>0:
310 self.set_block(b)
311 b = b - 1
312 print "NO PRECEDING 'BIG' BLOCKS"
313
314 def on_nextbigbutton_clicked(self,*args):
315 b = self.block + 1
316 n = self.im.getNumBlocks()
317 while b < n:
318 rl,cl,rh,ch = self.im.getBlockLocation(b)
319 if rh-rl > 0 or ch-cl>0:
320 self.set_block(b)
321 b = b + 1
322 print "NO FOLLOWING 'BIG' BLOCKS"
323
324 def on_blockentry_key_press_event(self,widget,event):
325 keyname = gtk.gdk.keyval_name(event.keyval)
326 print "KEY ",keyname
327 if keyname=="Return":
328 self.set_block( int(self.blockentry.get_text()) )
329
330 def on_zoominbutton_clicked(self,*args):
331 z = int( math.log(self.zoom)/math.log(2) )
332 z = pow(2,z + 1);
333 self.set_zoom(z)
334
335 def on_zoomoutbutton_clicked(self,*args):
336 z = int( math.log(self.zoom)/math.log(2) + 0.999)
337 z = pow(2,z - 1);
338 self.set_zoom(z)
339
340 def on_zoomentry_key_press_event(self,widget,event):
341 keyname = gtk.gdk.keyval_name(event.keyval)
342 print "KEY ",keyname
343 if keyname=="Return":
344 t = self.zoomentry.get_text()
345 m = ZOOM_RE.match(t)
346 if not m:
347 self.zoomentry.set_text("%d %%" % int(self.zoom*100))
348 for mm in m:
349 print m
350 self.set_zoom( int(self.zoomentry.get_text()) )
351
352 def on_imageevent_motion_notify_event(self,widget,event):
353 self.show_cursor(event.x, event.y)
354
355 def on_imageevent_button_press_event(self,widget,event):
356 self.show_cursor(event.x, event.y)
357
358
359 # The following is from
360 # http://www.experts-exchange.com/Programming/Programming_Languages/Python/Q_21719649.html
361 # it's still buggy.
362
363 def fold(data):
364 """ fold sorted numeric sequence data into ranged representation:
365 >>> fold([1, 4,5,6, 10, 15,16,17,18, 22, 25,26,27,28])
366 '[1,4-6,10,15-18,22,25-28]'
367 """
368 folded = []
369 for k, g in groupby(enumerate(sorted(data)), lambda (i,x):i-x):
370 seq = map(itemgetter(1), g)
371 if len(seq) > 1:
372 x = '%s-%s' % (seq[0], seq[-1])
373 else:
374 x = str(seq[0])
375 folded.append(x)
376 return folded and '[%s]' % ','.join(folded) or ''
377
378 def reduce(names):
379 """reduce a list of items nto something more readable:
380 >>> 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()
381 >>> res = reduce(data)
382 >>> for k in sorted(res):
383 ... print '%s: %s' % (k, res[k])
384 C: T, delta[1-3,5], h, p, x
385 C.sat: p, x
386 """
387 data = sorted([n.split('.') for n in sorted(names)], key=len)
388 res = {}
389 for k, g in groupby(data, lambda x: len(x)):
390 if k == 1:
391 indexed = {}
392 seq = set(get(indexed, item) for item in g)
393 res['[global]'] = [ i+fold(indexed.get(i, [])) for i in sorted(seq) ]
394 else:
395 for key, g1 in groupby(g, lambda x: '.'.join(x[:-1])):
396 indexed = {}
397 seq = set(get(indexed, item) for item in g1)
398 res[key] = [ i+fold(indexed.get(i, [])) for i in sorted(seq) ]
399 return res
400
401 def get(indexed, item):
402 item = item[-1]
403 if item.endswith(']'):
404 item, idx = item[:-1].split('[')
405 indexed.setdefault(item, []).append(int(idx))
406 return item

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