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 |
johnpye |
735 |
from infodialog import * |
11 |
johnpye |
351 |
|
12 |
johnpye |
284 |
ZOOM_RE = re.compile(r"([0-9]+)\s*%?") |
13 |
johnpye |
895 |
MAX_ZOOM_SIZE = float(2000) # float |
14 |
|
|
MAX_ZOOM_RATIO = float(16) # float |
15 |
johnpye |
287 |
AT_BOUND_TOL = 0.0001; |
16 |
johnpye |
284 |
|
17 |
johnpye |
280 |
class DiagnoseWindow: |
18 |
johnpye |
351 |
def __init__(self,browser,block=0): |
19 |
johnpye |
280 |
self.browser=browser |
20 |
johnpye |
437 |
_xml = gtk.glade.XML(browser.glade_file,"diagnosewin") |
21 |
johnpye |
280 |
_xml.signal_autoconnect(self) |
22 |
|
|
|
23 |
|
|
self.window = _xml.get_widget("diagnosewin") |
24 |
johnpye |
328 |
self.window.set_transient_for(self.browser.window) |
25 |
|
|
|
26 |
johnpye |
533 |
try: |
27 |
|
|
_icon = gtk.Image() |
28 |
|
|
_iconpath = browser.assets_dir+'diagnose'+config.ICON_EXTENSION |
29 |
|
|
print "ICON PATH =",_iconpath |
30 |
|
|
_icon.set_from_file(_iconpath) |
31 |
|
|
print "ICON = ",_icon |
32 |
|
|
self.window.set_icon(_icon) |
33 |
|
|
except: |
34 |
|
|
pass |
35 |
johnpye |
455 |
|
36 |
johnpye |
284 |
self.imagescroll = _xml.get_widget("imagescroll") |
37 |
johnpye |
282 |
self.image = _xml.get_widget("image") |
38 |
johnpye |
280 |
self.blockentry = _xml.get_widget("blockentry") |
39 |
johnpye |
284 |
self.zoomentry = _xml.get_widget("zoomentry") |
40 |
johnpye |
280 |
|
41 |
johnpye |
736 |
self.var = None; self.rel = None |
42 |
|
|
self.varname = _xml.get_widget("varname") |
43 |
|
|
self.varval = _xml.get_widget("varval") |
44 |
|
|
self.varinfobutton = _xml.get_widget("varinfobutton") |
45 |
|
|
self.relname = _xml.get_widget("relname") |
46 |
|
|
self.relresid = _xml.get_widget("relresid") |
47 |
johnpye |
735 |
self.relinfobutton = _xml.get_widget("relinfobutton") |
48 |
johnpye |
286 |
|
49 |
johnpye |
280 |
self.varview = _xml.get_widget("varview") |
50 |
|
|
self.varbuf = gtk.TextBuffer() |
51 |
|
|
self.varview.set_buffer(self.varbuf) |
52 |
|
|
self.varcollapsed = _xml.get_widget("varcollapsed") |
53 |
|
|
self.relview = _xml.get_widget("relview") |
54 |
|
|
self.relcollapsed = _xml.get_widget("relcollapsed") |
55 |
|
|
self.relvalues = _xml.get_widget("relvalues") |
56 |
|
|
self.rellabels = _xml.get_widget("rellabels") |
57 |
|
|
self.relrels = _xml.get_widget("relrels") |
58 |
|
|
self.relresids = _xml.get_widget("relresids") |
59 |
|
|
self.relbuf = gtk.TextBuffer() |
60 |
|
|
self.relview.set_buffer(self.relbuf) |
61 |
|
|
|
62 |
johnpye |
294 |
self.im = None |
63 |
johnpye |
285 |
self.block = 0 |
64 |
johnpye |
294 |
self.apply_prefs() |
65 |
|
|
|
66 |
johnpye |
280 |
self.prepare_data() |
67 |
johnpye |
285 |
self.fill_values(block) # block zero |
68 |
johnpye |
280 |
|
69 |
|
|
def run(self): |
70 |
|
|
self.window.run() |
71 |
|
|
self.window.hide() |
72 |
|
|
|
73 |
johnpye |
294 |
def apply_prefs(self): |
74 |
johnpye |
319 |
vc = self.browser.prefs.getBoolPref("Diagnose","varcollapsed",True) |
75 |
|
|
|
76 |
johnpye |
294 |
print "VARCOLLAPSED =",vc |
77 |
|
|
self.varcollapsed.set_active(vc) |
78 |
johnpye |
319 |
self.relcollapsed.set_active(self.browser.prefs.getBoolPref("Diagnose","relcollapsed",True)) |
79 |
johnpye |
294 |
|
80 |
johnpye |
280 |
def prepare_data(self): |
81 |
|
|
# convert incidence map to pylab numarray type: |
82 |
|
|
print "PREPARING DATA" |
83 |
|
|
self.im = self.browser.sim.getIncidenceMatrix() |
84 |
|
|
self.data = self.im.getIncidenceData() |
85 |
|
|
print "DATA LOADED" |
86 |
|
|
|
87 |
johnpye |
284 |
self.zoom=1; |
88 |
johnpye |
280 |
|
89 |
|
|
def fill_values(self, block): |
90 |
johnpye |
319 |
|
91 |
johnpye |
283 |
try: |
92 |
johnpye |
736 |
if self.im.getNumBlocks()==0: |
93 |
|
|
print "NO BLOCKS!" |
94 |
|
|
self.image.set_from_stock(gtk.STOCK_DIALOG_ERROR |
95 |
|
|
,gtk.ICON_SIZE_DIALOG |
96 |
|
|
) |
97 |
|
|
self.browser.reporter.reportError( |
98 |
|
|
"Can't 'Diagnose blocks' until solver has been used." |
99 |
|
|
) |
100 |
|
|
return; |
101 |
johnpye |
283 |
rl,cl,rh,ch = self.im.getBlockLocation(block) |
102 |
|
|
except IndexError: |
103 |
johnpye |
319 |
if block >= self.im.getNumBlocks(): |
104 |
|
|
block = self.im.getNumBlocks() - 1 |
105 |
|
|
rl,cl,rh,ch = self.im.getBlockLocation(block) |
106 |
|
|
else: |
107 |
|
|
print "BLOCK INDEX ERROR: block =",block |
108 |
|
|
self.blockentry.set_text(str(self.block)) |
109 |
|
|
return |
110 |
|
|
except RuntimeError,e: |
111 |
|
|
print "ERROR GETTING BLOCK LOCATION:",str(e) |
112 |
johnpye |
285 |
self.blockentry.set_text(str(self.block)) |
113 |
johnpye |
283 |
return |
114 |
johnpye |
285 |
|
115 |
johnpye |
280 |
self.block = block |
116 |
|
|
self.blockentry.set_text(str(block)) |
117 |
johnpye |
283 |
|
118 |
johnpye |
286 |
self.rl = rl |
119 |
|
|
self.cl = cl |
120 |
|
|
self.rh = rh |
121 |
|
|
self.ch = ch |
122 |
|
|
|
123 |
johnpye |
283 |
nr = int(rh-rl+1); |
124 |
|
|
nc = int(ch-cl+1); |
125 |
|
|
|
126 |
johnpye |
669 |
print "STARTING IMAGE CREATION" |
127 |
johnpye |
282 |
# refer http://pygtk.org/pygtk2tutorial/sec-DrawingMethods.html |
128 |
|
|
c = chr(255) |
129 |
johnpye |
283 |
b = nr*nc*3*[c] |
130 |
|
|
rowstride = 3 * nc |
131 |
|
|
|
132 |
|
|
blackdot = [chr(0)]*3; |
133 |
|
|
reddot = [chr(255), chr(0), chr(0)] |
134 |
|
|
pinkdot = [chr(255), chr(127), chr(127)] |
135 |
|
|
skydot = [chr(127), chr(127), chr(255)] |
136 |
|
|
bluedot = [chr(0), chr(0), chr(255)] |
137 |
johnpye |
285 |
hotpinkdot = [chr(255), chr(47), chr(179)] # very big (+/-) |
138 |
|
|
brightbluedot = [chr(71), chr(157), chr(255)] # very small (+/-) |
139 |
|
|
greendot = [chr(87), chr(193), chr(70)] # close to 1 |
140 |
|
|
orangedot = [chr(255), chr(207), chr(61)] # 10-1000 |
141 |
|
|
bluegreendot = [chr(70), chr(221), chr(181)] # 0.001 - 0.1 |
142 |
johnpye |
280 |
for i in self.data: |
143 |
johnpye |
283 |
if i.row < rl or i.row > rh or i.col < cl or i.col > ch: |
144 |
|
|
continue |
145 |
|
|
r = i.row - rl; |
146 |
|
|
c = i.col - cl; |
147 |
|
|
pos = rowstride*r + 3*c |
148 |
|
|
dot = blackdot; |
149 |
|
|
var = self.im.getVariable(i.col); |
150 |
johnpye |
287 |
if abs( (var.getValue()-var.getUpperBound())/ var.getNominal() ) < AT_BOUND_TOL: |
151 |
|
|
dot = reddot |
152 |
|
|
elif abs( var.getValue() - var.getLowerBound() ) / var.getNominal() < AT_BOUND_TOL: |
153 |
|
|
dot = reddot |
154 |
|
|
else: |
155 |
|
|
rat = var.getValue() / var.getNominal() |
156 |
|
|
if rat!=0: |
157 |
|
|
try: |
158 |
|
|
val = abs(rat) |
159 |
|
|
if abs(rat) > 1000: |
160 |
|
|
dot = hotpinkdot |
161 |
|
|
elif abs(rat) > 10: |
162 |
|
|
dot = orangedot |
163 |
|
|
elif abs(rat) < 0.001: |
164 |
|
|
dot = brightbluedot |
165 |
|
|
elif abs(rat) < 10 and abs(rat) > 0.1: |
166 |
|
|
dot = greendot |
167 |
|
|
elif abs(rat) > 0.001 and abs(rat) < 0.1: |
168 |
|
|
dot = bluegreendot |
169 |
|
|
else: |
170 |
|
|
dot = blackdot |
171 |
|
|
except ValueError, e: |
172 |
|
|
pass |
173 |
johnpye |
284 |
#print "DOT: ",dot |
174 |
johnpye |
283 |
b[pos], b[pos+1], b[pos+2] = dot |
175 |
|
|
|
176 |
johnpye |
282 |
d = ''.join(b) |
177 |
johnpye |
283 |
|
178 |
johnpye |
669 |
print "DONE IMAGE CREATION" |
179 |
johnpye |
282 |
|
180 |
johnpye |
284 |
self.pixbuf = gtk.gdk.pixbuf_new_from_data(d, gtk.gdk.COLORSPACE_RGB, False, 8 \ |
181 |
|
|
, nc, nr, rowstride); |
182 |
johnpye |
283 |
|
183 |
johnpye |
284 |
self.nr = nr |
184 |
|
|
self.nc = nc |
185 |
|
|
self.zoom = -1 # to fit, up to max 16x |
186 |
|
|
self.do_zoom() |
187 |
johnpye |
283 |
|
188 |
johnpye |
669 |
print "DONE IMAGE TRANSFER TO SERVER" |
189 |
johnpye |
283 |
|
190 |
johnpye |
284 |
self.fill_var_names() |
191 |
|
|
self.fill_rel_names() |
192 |
johnpye |
286 |
|
193 |
johnpye |
735 |
self.fill_selection_info() |
194 |
johnpye |
280 |
|
195 |
johnpye |
669 |
print "DONE FILL VALUES" |
196 |
johnpye |
286 |
|
197 |
johnpye |
735 |
def fill_selection_info(self): |
198 |
|
|
if self.var: |
199 |
|
|
self.varname.set_text(self.var.getName()) |
200 |
|
|
self.varval.set_text(str(self.var.getValue())) |
201 |
|
|
self.varinfobutton.set_sensitive(True) |
202 |
|
|
else: |
203 |
|
|
self.varname.set_text("") |
204 |
|
|
self.varval.set_text("") |
205 |
|
|
self.varinfobutton.set_sensitive(False) |
206 |
|
|
|
207 |
|
|
if self.rel: |
208 |
|
|
self.relname.set_text(self.rel.getName()) |
209 |
|
|
self.relresid.set_text(str(self.rel.getResidual())) |
210 |
|
|
self.relinfobutton.set_sensitive(True) |
211 |
|
|
else: |
212 |
|
|
self.relname.set_text("") |
213 |
|
|
self.relresid.set_text("") |
214 |
|
|
self.relinfobutton.set_sensitive(False) |
215 |
|
|
|
216 |
johnpye |
284 |
def do_zoom(self): |
217 |
|
|
if self.zoom == -1: |
218 |
|
|
w, h = self.imagescroll.size_request() |
219 |
|
|
#print "SCALE TO FIX, w=%d, h=%d" % (w,h) |
220 |
|
|
if self.nc/self.nr > w/h: |
221 |
|
|
# a 'wide' image |
222 |
johnpye |
895 |
self.zoom = float(w) / self.nc |
223 |
johnpye |
284 |
else: |
224 |
johnpye |
895 |
self.zoom = float(h) / self.nr |
225 |
johnpye |
283 |
|
226 |
johnpye |
1109 |
#self.browser.reporter.reportNote("Diagnose window: preliminary calculated zoom = %f (nr = %d, nc = %d)" % (self.zoom, self.nr, self.nc)) |
227 |
johnpye |
895 |
|
228 |
|
|
|
229 |
johnpye |
284 |
if self.zoom > MAX_ZOOM_RATIO: |
230 |
|
|
self.zoom = MAX_ZOOM_RATIO |
231 |
johnpye |
280 |
|
232 |
johnpye |
284 |
if self.zoom * self.nc > MAX_ZOOM_SIZE or self.zoom * self.nr > MAX_ZOOM_SIZE: |
233 |
johnpye |
895 |
self.browser.reporter.reportNode("image is too big, reducing to MAX_ZOOM_SIZE = %f" % MAX_ZOOM_SIZE); |
234 |
johnpye |
284 |
self.zoom = MAX_ZOOM_SIZE / max(self.nc,self.nr) |
235 |
johnpye |
283 |
|
236 |
johnpye |
1109 |
#self.browser.reporter.reportNote("Diagnose window: matrix zoom = %f" % self.zoom) |
237 |
johnpye |
284 |
w = int(self.zoom * self.nc); |
238 |
|
|
h = int(self.zoom * self.nr); |
239 |
|
|
|
240 |
|
|
self.zoomentry.set_text("%d %%" % (int(self.zoom*100)) ) |
241 |
johnpye |
280 |
|
242 |
johnpye |
284 |
if self.zoom < 2: |
243 |
|
|
pb1 = self.pixbuf.scale_simple(w,h,gtk.gdk.INTERP_BILINEAR) |
244 |
|
|
else: |
245 |
|
|
pb1 = self.pixbuf.scale_simple(w,h,gtk.gdk.INTERP_NEAREST) |
246 |
|
|
|
247 |
|
|
self.image.set_from_pixbuf(pb1) |
248 |
|
|
|
249 |
johnpye |
280 |
def fill_var_names(self): |
250 |
johnpye |
669 |
print "FILL VAR NAMES" |
251 |
|
|
|
252 |
johnpye |
280 |
names = [str(i) for i in self.im.getBlockVars(self.block)] |
253 |
johnpye |
669 |
|
254 |
johnpye |
895 |
#print "NAMES:",names |
255 |
johnpye |
669 |
|
256 |
johnpye |
280 |
if self.varcollapsed.get_active(): |
257 |
johnpye |
287 |
res = reduce(names) |
258 |
johnpye |
280 |
rows = [] |
259 |
|
|
for k in res: |
260 |
|
|
if k=="": |
261 |
|
|
for r in res[k]: |
262 |
|
|
rows.append(r) |
263 |
|
|
else: |
264 |
|
|
rows.append( '%s:\n\t%s' % (k, "\n\t".join(res[k])) ) |
265 |
|
|
text = "\n".join(rows) |
266 |
|
|
else: |
267 |
|
|
text = "\n".join(names) |
268 |
|
|
self.varbuf.set_text(text) |
269 |
|
|
|
270 |
johnpye |
669 |
print "DONE VAR NAMES" |
271 |
|
|
|
272 |
johnpye |
280 |
def fill_rel_names(self): |
273 |
johnpye |
669 |
print "REL NAMES" |
274 |
|
|
|
275 |
|
|
rels = self.im.getBlockRels(self.block) |
276 |
|
|
|
277 |
|
|
print "GOT RELS, NOW GETTING NAMES" |
278 |
|
|
|
279 |
|
|
names = [str(i) for i in rels] |
280 |
|
|
|
281 |
johnpye |
895 |
#print "NAMES =",names |
282 |
johnpye |
669 |
|
283 |
johnpye |
280 |
if self.relcollapsed.get_active(): |
284 |
johnpye |
287 |
res = reduce(names) |
285 |
|
|
rows = [] |
286 |
|
|
for k in res: |
287 |
|
|
if k=="": |
288 |
|
|
for r in res[k]: |
289 |
|
|
rows.append(r) |
290 |
|
|
else: |
291 |
|
|
rows.append( '%s:\n\t%s' % (k, "\n\t".join(res[k])) ) |
292 |
|
|
text = "\n".join(rows) |
293 |
johnpye |
280 |
else: |
294 |
|
|
text = "\n".join(names) |
295 |
|
|
self.relbuf.set_text(text) |
296 |
|
|
|
297 |
johnpye |
669 |
print "DONE REL NAMES" |
298 |
|
|
|
299 |
johnpye |
280 |
def set_block(self, block): |
300 |
|
|
self.fill_values(block) |
301 |
|
|
|
302 |
johnpye |
284 |
def set_zoom(self,zoom): |
303 |
|
|
self.zoom = zoom |
304 |
|
|
self.do_zoom() |
305 |
|
|
|
306 |
johnpye |
286 |
def show_cursor(self,x,y): |
307 |
|
|
c = self.cl + int(x/self.zoom) |
308 |
|
|
r = self.rl + int(y / self.zoom) |
309 |
|
|
if c > self.ch or r > self.rh: |
310 |
|
|
#print "OUT OF RANGE" |
311 |
|
|
return |
312 |
johnpye |
735 |
self.var = self.im.getVariable(c) |
313 |
|
|
self.rel = self.im.getRelation(r) |
314 |
|
|
self.fill_selection_info() |
315 |
johnpye |
286 |
|
316 |
|
|
# GUI EVENT HOOKS----------------------------------------------------------- |
317 |
|
|
|
318 |
johnpye |
735 |
def on_diagnosewin_close(self,*args): |
319 |
|
|
self.window.response(gtk.RESPONSE_CLOSE); |
320 |
|
|
|
321 |
|
|
# incidence data view |
322 |
|
|
|
323 |
johnpye |
280 |
def on_varcollapsed_toggled(self,*args): |
324 |
johnpye |
294 |
vc = self.varcollapsed.get_active() |
325 |
|
|
self.browser.prefs.setBoolPref("Diagnose","varcollapsed",vc) |
326 |
|
|
if self.im: |
327 |
|
|
self.fill_var_names() |
328 |
johnpye |
280 |
|
329 |
|
|
def on_relcollapsed_toggled(self,*args): |
330 |
johnpye |
294 |
rc = self.varcollapsed.get_active() |
331 |
|
|
self.browser.prefs.setBoolPref("Diagnose","relcollapsed",rc) |
332 |
|
|
if self.im: |
333 |
|
|
self.fill_rel_names() |
334 |
johnpye |
280 |
|
335 |
johnpye |
735 |
# detailed information about vars and rels (solver-side information!) |
336 |
|
|
|
337 |
|
|
def on_varinfobutton_clicked(self,*args): |
338 |
|
|
title = "Variable '%s'" % self.var |
339 |
|
|
text = "%s\n%s\n" % (title,"(from the solver's view)") |
340 |
johnpye |
736 |
|
341 |
|
|
_rows = { |
342 |
|
|
"Value": self.var.getValue() |
343 |
|
|
,"Nominal": self.var.getNominal() |
344 |
|
|
,"Lower bound": self.var.getLowerBound() |
345 |
|
|
,"Upper bound": self.var.getUpperBound() |
346 |
|
|
} |
347 |
|
|
for k,v in _rows.iteritems(): |
348 |
johnpye |
737 |
text += "\n %s\t%s" % (k,value_human(v)) |
349 |
johnpye |
735 |
|
350 |
johnpye |
737 |
text += "\n\nIncident with %d relations:" % self.var.getNumIncidentRelations() |
351 |
johnpye |
735 |
for r in self.var.getIncidentRelations(): |
352 |
johnpye |
736 |
text += "\n %s" % r.getName() |
353 |
johnpye |
735 |
|
354 |
johnpye |
737 |
_dialog = InfoDialog(self.browser,self.window,text,title,tabs=(150,300)) |
355 |
johnpye |
735 |
_dialog.run() |
356 |
|
|
|
357 |
|
|
def on_relinfobutton_clicked(self,*args): |
358 |
|
|
title = "Relation '%s'" % self.rel |
359 |
|
|
text = "%s\n%s\n" % (title,"(from the solver's view)") |
360 |
johnpye |
737 |
text += "\n %s\t%15f" % ("Residual", self.rel.getResidual()) |
361 |
johnpye |
735 |
|
362 |
johnpye |
736 |
text += "\n\nRelation expression:\n" |
363 |
|
|
text += self.rel.getRelationAsString() |
364 |
|
|
|
365 |
johnpye |
737 |
text += "\n\nIncident with %d variables:" % self.rel.getNumIncidentVariables() |
366 |
|
|
for v in self.rel.getIncidentVariables(): |
367 |
|
|
text += "\n %s\t= %s" % ( v.getName(),value_human(v.getValue()) ) |
368 |
|
|
|
369 |
|
|
_dialog = InfoDialog(self.browser,self.window,text,title,tabs=(150,300)) |
370 |
johnpye |
735 |
_dialog.run() |
371 |
|
|
|
372 |
|
|
|
373 |
|
|
# block navigation |
374 |
|
|
|
375 |
johnpye |
280 |
def on_nextbutton_clicked(self,*args): |
376 |
|
|
self.set_block(self.block + 1) |
377 |
|
|
|
378 |
|
|
def on_prevbutton_clicked(self,*args): |
379 |
johnpye |
290 |
self.set_block(self.block - 1) |
380 |
johnpye |
280 |
|
381 |
johnpye |
290 |
def on_prevbigbutton_clicked(self,*args): |
382 |
|
|
b = self.block - 1 |
383 |
johnpye |
291 |
while b >= 0: |
384 |
johnpye |
290 |
rl,cl,rh,ch = self.im.getBlockLocation(b) |
385 |
|
|
if rh-rl > 0 or ch-cl>0: |
386 |
|
|
self.set_block(b) |
387 |
|
|
b = b - 1 |
388 |
|
|
print "NO PRECEDING 'BIG' BLOCKS" |
389 |
|
|
|
390 |
|
|
def on_nextbigbutton_clicked(self,*args): |
391 |
|
|
b = self.block + 1 |
392 |
|
|
n = self.im.getNumBlocks() |
393 |
|
|
while b < n: |
394 |
|
|
rl,cl,rh,ch = self.im.getBlockLocation(b) |
395 |
|
|
if rh-rl > 0 or ch-cl>0: |
396 |
|
|
self.set_block(b) |
397 |
|
|
b = b + 1 |
398 |
|
|
print "NO FOLLOWING 'BIG' BLOCKS" |
399 |
|
|
|
400 |
johnpye |
283 |
def on_blockentry_key_press_event(self,widget,event): |
401 |
|
|
keyname = gtk.gdk.keyval_name(event.keyval) |
402 |
|
|
print "KEY ",keyname |
403 |
|
|
if keyname=="Return": |
404 |
|
|
self.set_block( int(self.blockentry.get_text()) ) |
405 |
johnpye |
280 |
|
406 |
johnpye |
735 |
# zoom in and out |
407 |
|
|
|
408 |
johnpye |
284 |
def on_zoominbutton_clicked(self,*args): |
409 |
|
|
z = int( math.log(self.zoom)/math.log(2) ) |
410 |
|
|
z = pow(2,z + 1); |
411 |
|
|
self.set_zoom(z) |
412 |
|
|
|
413 |
|
|
def on_zoomoutbutton_clicked(self,*args): |
414 |
|
|
z = int( math.log(self.zoom)/math.log(2) + 0.999) |
415 |
|
|
z = pow(2,z - 1); |
416 |
|
|
self.set_zoom(z) |
417 |
|
|
|
418 |
|
|
def on_zoomentry_key_press_event(self,widget,event): |
419 |
|
|
keyname = gtk.gdk.keyval_name(event.keyval) |
420 |
|
|
print "KEY ",keyname |
421 |
|
|
if keyname=="Return": |
422 |
|
|
t = self.zoomentry.get_text() |
423 |
|
|
m = ZOOM_RE.match(t) |
424 |
|
|
if not m: |
425 |
|
|
self.zoomentry.set_text("%d %%" % int(self.zoom*100)) |
426 |
|
|
for mm in m: |
427 |
|
|
print m |
428 |
|
|
self.set_zoom( int(self.zoomentry.get_text()) ) |
429 |
|
|
|
430 |
johnpye |
735 |
# clicking in incidence matrix to get updated information at RHS |
431 |
|
|
|
432 |
johnpye |
286 |
def on_imageevent_motion_notify_event(self,widget,event): |
433 |
|
|
self.show_cursor(event.x, event.y) |
434 |
|
|
|
435 |
|
|
def on_imageevent_button_press_event(self,widget,event): |
436 |
|
|
self.show_cursor(event.x, event.y) |
437 |
|
|
|
438 |
|
|
|
439 |
johnpye |
737 |
def value_human(v): |
440 |
|
|
if v==0 or abs( math.log10(abs(v)) )<8: |
441 |
|
|
return "%f" % v |
442 |
|
|
return "%e" % v |
443 |
|
|
|
444 |
|
|
#--------------------------------------- |
445 |
|
|
# Procedures to 'fold' a list of items from a hierarchy |
446 |
johnpye |
280 |
# http://www.experts-exchange.com/Programming/Programming_Languages/Python/Q_21719649.html |
447 |
johnpye |
737 |
# It's still buggy, I think |
448 |
johnpye |
280 |
|
449 |
|
|
def fold(data): |
450 |
|
|
""" fold sorted numeric sequence data into ranged representation: |
451 |
|
|
>>> fold([1, 4,5,6, 10, 15,16,17,18, 22, 25,26,27,28]) |
452 |
|
|
'[1,4-6,10,15-18,22,25-28]' |
453 |
|
|
""" |
454 |
|
|
folded = [] |
455 |
johnpye |
287 |
for k, g in groupby(enumerate(sorted(data)), lambda (i,x):i-x): |
456 |
johnpye |
280 |
seq = map(itemgetter(1), g) |
457 |
|
|
if len(seq) > 1: |
458 |
|
|
x = '%s-%s' % (seq[0], seq[-1]) |
459 |
|
|
else: |
460 |
|
|
x = str(seq[0]) |
461 |
|
|
folded.append(x) |
462 |
|
|
return folded and '[%s]' % ','.join(folded) or '' |
463 |
|
|
|
464 |
johnpye |
287 |
def reduce(names): |
465 |
|
|
"""reduce a list of items nto something more readable: |
466 |
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() |
467 |
|
|
>>> res = reduce(data) |
468 |
|
|
>>> for k in sorted(res): |
469 |
|
|
... print '%s: %s' % (k, res[k]) |
470 |
|
|
C: T, delta[1-3,5], h, p, x |
471 |
|
|
C.sat: p, x |
472 |
|
|
""" |
473 |
johnpye |
287 |
data = sorted([n.split('.') for n in sorted(names)], key=len) |
474 |
johnpye |
280 |
res = {} |
475 |
|
|
for k, g in groupby(data, lambda x: len(x)): |
476 |
johnpye |
287 |
if k == 1: |
477 |
|
|
indexed = {} |
478 |
|
|
seq = set(get(indexed, item) for item in g) |
479 |
|
|
res['[global]'] = [ i+fold(indexed.get(i, [])) for i in sorted(seq) ] |
480 |
|
|
else: |
481 |
|
|
for key, g1 in groupby(g, lambda x: '.'.join(x[:-1])): |
482 |
|
|
indexed = {} |
483 |
|
|
seq = set(get(indexed, item) for item in g1) |
484 |
|
|
res[key] = [ i+fold(indexed.get(i, [])) for i in sorted(seq) ] |
485 |
johnpye |
280 |
return res |
486 |
|
|
|
487 |
|
|
def get(indexed, item): |
488 |
|
|
item = item[-1] |
489 |
|
|
if item.endswith(']'): |
490 |
|
|
item, idx = item[:-1].split('[') |
491 |
|
|
indexed.setdefault(item, []).append(int(idx)) |
492 |
|
|
return item |
493 |
johnpye |
737 |
|