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

Contents of /trunk/pygtk/interface/diagnose.py

Parent Directory Parent Directory | Revision Log Revision Log


Revision 286 - (show annotations) (download) (as text)
Thu Feb 9 07:36:39 2006 UTC (13 years, 9 months ago) by johnpye
File MIME type: text/x-python
File size: 8830 byte(s)
Added cursor to report mouse-over variable and residual
1 import gtk
2 import gtk.glade
3 import ascend
4 from itertools import groupby
5 from operator import itemgetter
6 import math
7 import re
8
9 ZOOM_RE = re.compile(r"([0-9]+)\s*%?")
10 MAX_ZOOM_SIZE = 2000
11 MAX_ZOOM_RATIO = 16
12
13 class DiagnoseWindow:
14 def __init__(self,GLADE_FILE,browser,block=0):
15 self.browser=browser
16 _xml = gtk.glade.XML(GLADE_FILE,"diagnosewin")
17 _xml.signal_autoconnect(self)
18
19 self.window = _xml.get_widget("diagnosewin")
20 self.imagescroll = _xml.get_widget("imagescroll")
21 self.image = _xml.get_widget("image")
22 self.blockentry = _xml.get_widget("blockentry")
23 self.zoomentry = _xml.get_widget("zoomentry")
24
25 self.varname = _xml.get_widget("varname");
26 self.varval = _xml.get_widget("varval");
27 self.relname = _xml.get_widget("relname");
28 self.relresid = _xml.get_widget("relresid");
29
30 self.varview = _xml.get_widget("varview")
31 self.varbuf = gtk.TextBuffer()
32 self.varview.set_buffer(self.varbuf)
33 self.varcollapsed = _xml.get_widget("varcollapsed")
34 self.relview = _xml.get_widget("relview")
35 self.relcollapsed = _xml.get_widget("relcollapsed")
36 self.relvalues = _xml.get_widget("relvalues")
37 self.rellabels = _xml.get_widget("rellabels")
38 self.relrels = _xml.get_widget("relrels")
39 self.relresids = _xml.get_widget("relresids")
40 self.relbuf = gtk.TextBuffer()
41 self.relview.set_buffer(self.relbuf)
42
43 self.block = 0
44 self.prepare_data()
45 self.fill_values(block) # block zero
46
47 def run(self):
48 self.window.run()
49 self.window.hide()
50
51 def prepare_data(self):
52 # convert incidence map to pylab numarray type:
53 print "PREPARING DATA"
54 self.im = self.browser.sim.getIncidenceMatrix()
55 self.data = self.im.getIncidenceData()
56 print "DATA LOADED"
57
58 self.zoom=1;
59
60 def fill_values(self, block):
61 try:
62 rl,cl,rh,ch = self.im.getBlockLocation(block)
63 except IndexError:
64 self.blockentry.set_text(str(self.block))
65 return
66 except RuntimeError:
67 self.blockentry.set_text(str(self.block))
68 return
69
70 self.block = block
71 self.blockentry.set_text(str(block))
72
73 self.rl = rl
74 self.cl = cl
75 self.rh = rh
76 self.ch = ch
77
78 nr = int(rh-rl+1);
79 nc = int(ch-cl+1);
80
81 #print "STARTING IMAGE CREATION"
82 # refer http://pygtk.org/pygtk2tutorial/sec-DrawingMethods.html
83 c = chr(255)
84 b = nr*nc*3*[c]
85 rowstride = 3 * nc
86
87 blackdot = [chr(0)]*3;
88 reddot = [chr(255), chr(0), chr(0)]
89 pinkdot = [chr(255), chr(127), chr(127)]
90 skydot = [chr(127), chr(127), chr(255)]
91 bluedot = [chr(0), chr(0), chr(255)]
92 hotpinkdot = [chr(255), chr(47), chr(179)] # very big (+/-)
93 brightbluedot = [chr(71), chr(157), chr(255)] # very small (+/-)
94 greendot = [chr(87), chr(193), chr(70)] # close to 1
95 orangedot = [chr(255), chr(207), chr(61)] # 10-1000
96 bluegreendot = [chr(70), chr(221), chr(181)] # 0.001 - 0.1
97 for i in self.data:
98 if i.row < rl or i.row > rh or i.col < cl or i.col > ch:
99 continue
100 r = i.row - rl;
101 c = i.col - cl;
102 pos = rowstride*r + 3*c
103 dot = blackdot;
104 var = self.im.getVariable(i.col);
105 rat = var.getValue() / var.getNominal()
106 if rat!=0:
107 try:
108 val = abs(rat)
109 if abs(rat) > 1000:
110 dot = hotpinkdot
111 elif abs(rat) > 10:
112 dot = orangedot
113 elif abs(rat) < 0.001:
114 dot = brightbluedot
115 elif abs(rat) < 10 and abs(rat) > 0.1:
116 dot = greendot
117 elif abs(rat) > 0.001 and abs(rat) < 0.1:
118 dot = bluegreendot
119 else:
120 dot = blackdot
121 except ValueError, e:
122 pass
123 #print "DOT: ",dot
124 b[pos], b[pos+1], b[pos+2] = dot
125
126 d = ''.join(b)
127
128 #print "DONE IMAGE CREATION"
129
130 self.pixbuf = gtk.gdk.pixbuf_new_from_data(d, gtk.gdk.COLORSPACE_RGB, False, 8 \
131 , nc, nr, rowstride);
132
133 self.nr = nr
134 self.nc = nc
135 self.zoom = -1 # to fit, up to max 16x
136 self.do_zoom()
137
138 #print "DONE IMAGE TRANSFER TO SERVER"
139
140 self.fill_var_names()
141 self.fill_rel_names()
142
143 self.varname.set_text("");
144 self.varval.set_text("");
145 self.relname.set_text("");
146 self.relresid.set_text("");
147
148
149 def do_zoom(self):
150 if self.zoom == -1:
151 w, h = self.imagescroll.size_request()
152 #print "SCALE TO FIX, w=%d, h=%d" % (w,h)
153 if self.nc/self.nr > w/h:
154 # a 'wide' image
155 self.zoom = w / self.nc
156 else:
157 self.zoom = h / self.nr
158
159 if self.zoom > MAX_ZOOM_RATIO:
160 self.zoom = MAX_ZOOM_RATIO
161
162 if self.zoom * self.nc > MAX_ZOOM_SIZE or self.zoom * self.nr > MAX_ZOOM_SIZE:
163 self.zoom = MAX_ZOOM_SIZE / max(self.nc,self.nr)
164
165 w = int(self.zoom * self.nc);
166 h = int(self.zoom * self.nr);
167
168 self.zoomentry.set_text("%d %%" % (int(self.zoom*100)) )
169
170 if self.zoom < 2:
171 pb1 = self.pixbuf.scale_simple(w,h,gtk.gdk.INTERP_BILINEAR)
172 else:
173 pb1 = self.pixbuf.scale_simple(w,h,gtk.gdk.INTERP_NEAREST)
174
175 self.image.set_from_pixbuf(pb1)
176
177 def fill_var_names(self):
178 names = [str(i) for i in self.im.getBlockVars(self.block)]
179 if self.varcollapsed.get_active():
180 res = collapse(names)
181 rows = []
182 for k in res:
183 if k=="":
184 for r in res[k]:
185 rows.append(r)
186 else:
187 rows.append( '%s:\n\t%s' % (k, "\n\t".join(res[k])) )
188 text = "\n".join(rows)
189 else:
190 text = "\n".join(names)
191 self.varbuf.set_text(text)
192
193 def fill_rel_names(self):
194 names = [str(i) for i in self.im.getBlockRels(self.block)]
195 if self.relcollapsed.get_active():
196 text = "\n".join(collapse(names))
197 else:
198 text = "\n".join(names)
199 self.relbuf.set_text(text)
200
201 def set_block(self, block):
202 self.fill_values(block)
203
204 def set_zoom(self,zoom):
205 self.zoom = zoom
206 self.do_zoom()
207
208 def show_cursor(self,x,y):
209 c = self.cl + int(x/self.zoom)
210 r = self.rl + int(y / self.zoom)
211 if c > self.ch or r > self.rh:
212 #print "OUT OF RANGE"
213 return
214 var = self.im.getVariable(c)
215 self.varname.set_text(var.getName())
216 self.varval.set_text(str(var.getValue()))
217 rel = self.im.getRelation(r)
218 self.relname.set_text(rel.getName())
219 self.relresid.set_text(str(rel.getResidual()))
220
221 # GUI EVENT HOOKS-----------------------------------------------------------
222
223 def on_varcollapsed_toggled(self,*args):
224 print "COLLAPSED-TOGGLED"
225 self.fill_var_names()
226
227 def on_relcollapsed_toggled(self,*args):
228 print "COLLAPSED-TOGGLED"
229 self.fill_rel_names()
230
231 def on_nextbutton_clicked(self,*args):
232 self.set_block(self.block + 1)
233
234 def on_prevbutton_clicked(self,*args):
235 self.set_block(self.block - 1)
236
237 def on_blockentry_key_press_event(self,widget,event):
238 keyname = gtk.gdk.keyval_name(event.keyval)
239 print "KEY ",keyname
240 if keyname=="Return":
241 self.set_block( int(self.blockentry.get_text()) )
242
243 def on_zoominbutton_clicked(self,*args):
244 z = int( math.log(self.zoom)/math.log(2) )
245 z = pow(2,z + 1);
246 self.set_zoom(z)
247
248 def on_zoomoutbutton_clicked(self,*args):
249 z = int( math.log(self.zoom)/math.log(2) + 0.999)
250 z = pow(2,z - 1);
251 self.set_zoom(z)
252
253 def on_zoomentry_key_press_event(self,widget,event):
254 keyname = gtk.gdk.keyval_name(event.keyval)
255 print "KEY ",keyname
256 if keyname=="Return":
257 t = self.zoomentry.get_text()
258 m = ZOOM_RE.match(t)
259 if not m:
260 self.zoomentry.set_text("%d %%" % int(self.zoom*100))
261 for mm in m:
262 print m
263 self.set_zoom( int(self.zoomentry.get_text()) )
264
265 def on_imageevent_motion_notify_event(self,widget,event):
266 self.show_cursor(event.x, event.y)
267
268 def on_imageevent_button_press_event(self,widget,event):
269 self.show_cursor(event.x, event.y)
270
271
272 # The following is from
273 # http://www.experts-exchange.com/Programming/Programming_Languages/Python/Q_21719649.html
274 # it's still buggy.
275
276 def fold(data):
277 """ fold sorted numeric sequence data into ranged representation:
278 >>> fold([1, 4,5,6, 10, 15,16,17,18, 22, 25,26,27,28])
279 '[1,4-6,10,15-18,22,25-28]'
280 """
281 folded = []
282 for k, g in groupby(enumerate(data), lambda (i,x):i-x):
283 seq = map(itemgetter(1), g)
284 if len(seq) > 1:
285 x = '%s-%s' % (seq[0], seq[-1])
286 else:
287 x = str(seq[0])
288 folded.append(x)
289 return folded and '[%s]' % ','.join(folded) or ''
290
291 def collapse(names):
292 """reduce a list of items into something more readable:
293 >>> 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()
294 >>> res = reduce(data)
295 >>> for k in sorted(res):
296 ... print '%s: %s' % (k, res[k])
297 C: T, delta[1-3,5], h, p, x
298 C.sat: p, x
299 """
300 data = sorted([n.split('.') for n in names], key=len)
301 res = {}
302 for k, g in groupby(data, lambda x: len(x)):
303 item = g.next()
304 assert len(item) == k
305 key = '.'.join(item[:-1]) or ''
306 indexed = {}
307 seq = set([get(indexed, item)])
308 for item in g:
309 seq.add(get(indexed, item))
310 res[key] = [i+fold(indexed.get(i, [])) for i in sorted(seq)]
311 return res
312
313 def get(indexed, item):
314 item = item[-1]
315 if item.endswith(']'):
316 item, idx = item[:-1].split('[')
317 indexed.setdefault(item, []).append(int(idx))
318 return item

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