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

Contents of /trunk/pygtk/diagnose.py

Parent Directory Parent Directory | Revision Log Revision Log


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

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