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

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

Parent Directory Parent Directory | Revision Log Revision Log


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

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