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

Contents of /trunk/pygtk/observer.py

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1387 - (show annotations) (download) (as text)
Sat Apr 7 14:43:31 2007 UTC (13 years, 9 months ago) by jpye
File MIME type: text/x-python
File size: 8930 byte(s)
Added plot support in Integrator output tabs.
Some other minor debugging for pylab integration and idaanalyse output.
1 import pygtk
2 pygtk.require('2.0')
3 import gtk
4 import gtk.glade
5 import pango
6 import os.path
7
8 OBSERVER_EDIT_COLOR = "#008800"
9 OBSERVER_NOEDIT_COLOR = "#000088"
10 OBSERVER_NORMAL_COLOR = "black"
11
12 # This code uses the techniques described in
13 # http://www.daa.com.au/pipermail/pygtk/2006-February/011777.html
14 # http://piman.livejournal.com/361173.html
15
16 OBSERVER_NUM=0
17
18 class ClickableTreeColumn(gtk.TreeViewColumn):
19 def __init__(self, title="", *args, **kwargs):
20 super(ClickableTreeColumn, self).__init__(None, *args, **kwargs)
21 self.label = gtk.Label("%s" % title)
22 self.label.show()
23 self.set_widget(self.label)
24
25 def do_connect(self):
26 """ Connect the defined 'on_click' method. Note: must be called after
27 this object (ClickableTreeColumn) has been added to the TreeView,
28 eg mytreeview.append_column(col). """
29 button = self.label.get_ancestor(gtk.Button)
30 h = button.connect("clicked",self.on_click)
31 #button.clicked()
32
33 def on_click(self,widget,*args):
34 print "RECEIVED EVENT"
35
36 class ObserverColumn:
37 """
38 A class to identify the instance that relates to a specify column
39 and the units of measurement and column title, etc.
40 """
41 def __init__(self,instance,index,name=None,units=None,browser=None):
42 self.instance = instance
43 self.name = name
44 self.index = index
45
46 if name==None:
47 if browser == None:
48 name = "UNNAMED"
49 else:
50 name = browser.sim.getInstanceName(instance)
51
52 if units == None:
53 units = instance.getType().getPreferredUnits()
54 if units == None:
55 units = instance.getType().getDimensions().getDefaultUnits()
56
57 uname = str(units.getName())
58 if len(uname) or uname.find("/")!=-1:
59 uname = "["+uname+"]"
60
61 if uname == "":
62 _title = "%s" % (name)
63 else:
64 _title = "%s / %s" % (name, uname)
65
66 self.title = _title
67 self.units = units
68 self.uname = uname
69 self.name = name
70
71 def __repr__(self):
72 return "ObserverColumn(name="+self.name+")"
73
74 def cellvalue(self, column, cell, model, iter):
75 #print "RENDERING COLUMN",self.index
76 _rowobject = model.get_value(iter,0)
77
78 cell.set_property('editable',False)
79 cell.set_property('weight',400)
80 try:
81 if _rowobject.active:
82 _rawval = self.instance.getRealValue()
83 if self.instance.getType().isRefinedSolverVar():
84 if self.instance.isFixed():
85 cell.set_property('editable',True)
86 cell.set_property('weight',700)
87 cell.set_property('foreground',OBSERVER_EDIT_COLOR)
88 else:
89 cell.set_property('foreground',OBSERVER_NOEDIT_COLOR)
90 else:
91 cell.set_property('foreground',OBSERVER_NORMAL_COLOR)
92 _rawval = _rowobject.values[self.index]
93 _dataval = _rawval / self.units.getConversion()
94 except IndexError:
95 _dataval = ""
96
97 cell.set_property('text', _dataval)
98
99 class ObserverRow:
100 """
101 Just a container for a vector of values, but with columns that
102 should correspond to those in the Observer object's vector of
103 ObserverColumn objects.
104 """
105 def __init__(self,values=None,active=True):
106 if values==None:
107 values=[]
108
109 self.values = values
110 self.active = active
111
112 def make_static(self,table):
113 self.active = False
114 print "TABLE COLS:",table.cols
115 print "ROW VALUES:",self.values
116 _v = []
117 for col in table.cols.values():
118 _v.append( col.instance.getRealValue() )
119 self.values = _v
120 print "Made static, values:",self.values
121
122 def get_values(self,table):
123 if not self.active:
124 vv = []
125 for k,v in table.cols.iteritems():
126 if k<len(self.values):
127 vv.append(self.values[k]/v.units.getConversion())
128 return vv
129 else:
130 return [col.instance.getRealValue()/col.units.getConversion() \
131 for index,col in table.cols.iteritems() \
132 ]
133
134 class ObserverTab:
135
136 def __init__(self,xml,browser,tab,name=None,alive=True):
137 global OBSERVER_NUM
138 self.colindex = 0
139 if name==None:
140 OBSERVER_NUM=OBSERVER_NUM+1
141 name = "Observer %d" % OBSERVER_NUM
142 self.name = name
143 self.browser=browser
144 xml.signal_autoconnect(self)
145 self.view = xml.get_widget('observerview')
146 self.tab = tab
147 self.alive=alive
148 if self.alive:
149 self.browser.reporter.reportNote("New observer is 'alive'")
150
151 self.keptimg = gtk.Image()
152 self.activeimg = gtk.Image()
153 self.activeimg.set_from_file(os.path.join(browser.options.assets_dir,"active.png"))
154 # create PixBuf objects from these?
155 self.rows = []
156 _store = gtk.TreeStore(object)
157 self.cols = {}
158
159 # create the 'active' pixbuf column
160 _renderer = gtk.CellRendererPixbuf()
161 _col = ClickableTreeColumn("")
162 _col.pack_start(_renderer,False)
163 _col.set_cell_data_func(_renderer, self.activepixbufvalue)
164 self.view.append_column(_col)
165 _col.do_connect()
166
167 # initially there will not be any other columns
168
169 if self.alive:
170 # for a 'live' Observer, create the 'active' bottom row
171 self.browser.reporter.reportNote("Adding empty row to store")
172 _row = ObserverRow()
173 self.activeiter = _store.append(None, [_row] )
174 self.rows.append(_row)
175
176 self.view.set_model(_store)
177 self.browser.reporter.reportNote("Created observer '%s'" % self.name)
178
179 def activepixbufvalue(self,column,cell,model,iter):
180 _rowobject = model.get_value(iter,0)
181 if _rowobject.active:
182 cell.set_property('pixbuf',self.activeimg.get_pixbuf())
183 else:
184 cell.set_property('pixbuf',self.keptimg.get_pixbuf())
185
186 def on_add_clicked(self,*args):
187 self.do_add_row()
188
189 def on_clear_clicked(self,*args):
190 _store = self.view.get_model()
191 _store.clear();
192 self.rows = []
193 self.activeiter = _store.append(None, [ObserverRow()] )
194
195 def plot(self,x=None,y=None,y2=None):
196 """create a plot from two columns in the ObserverTable"""
197 import platform
198 import matplotlib
199 matplotlib.use('GTKAgg')
200 import pylab
201 pylab.ioff()
202 if x is None or y is None:
203 if len(self.cols)<2:
204 raise Exception("Not enough columns to plot (need 2+)")
205 if x is None:
206 x=self.cols[0]
207 if y is None:
208 y=self.cols[1]
209
210 if x.__class__ is int and x>=0 and x<len(self.cols):
211 x=self.cols[x]
212 if y.__class__ is int and y>=0 and y<len(self.cols):
213 y=self.cols[y]
214 if y2.__class__ is int and y2>=0 and y2<len(self.cols):
215 y2=self.cols[y2]
216
217 ncols = 2
218 if y2 is not None:
219 ncols+=1
220
221 A = pylab.zeros((len(self.rows),ncols),'f')
222 for i in range(len(self.rows)):
223 r = self.rows[i].get_values(self)
224 A[i,0]=r[x.index]
225 A[i,1]=r[y.index]
226 if y2 is not None:
227 A[i,2]=r[y2.index]
228 print A
229 pylab.figure()
230 p1 = pylab.plot(A[:,0],A[:,1],'b-')
231 pylab.xlabel(x.title)
232 pylab.ylabel(y.title)
233
234 if y2 is not None:
235 ax2 = pylab.twinx()
236 p2 = pylab.plot(A[:,0],A[:,2],'r-')
237 pylab.ylabel(y2.title)
238 ax2.yaxis.tick_right()
239 pylab.legend([y.name,y2.name])
240
241 pylab.ion()
242 if platform.system()=="Windows":
243 pylab.show()
244 else:
245 pylab.show(False)
246
247 def on_plot_clicked(self,*args):
248 try:
249 self.plot()
250 except Exception,e:
251 self.browser.reporter.reportError(str(e))
252
253 def do_add_row(self,values=None):
254 _store = self.view.get_model()
255 if self.alive:
256 _row = ObserverRow()
257 self.rows.append(_row)
258 _oldrow = _store.get_value(self.activeiter,0)
259 _oldrow.make_static(self)
260 self.activeiter = _store.append(None,[_row])
261 _path = _store.get_path(self.activeiter)
262 _oldpath,_oldcol = self.view.get_cursor()
263 self.view.set_cursor(_path, _oldcol)
264 else:
265 _row = ObserverRow(values=values,active=False)
266 self.rows.append(_row)
267 _store.append(None,[_row])
268 #self.browser.reporter.reportNote("Added data row")
269
270 def on_view_cell_edited(self, renderer, path, newtext, col):
271 # we can assume it's always the self.activeiter that is edited...
272 if col.instance.isFixed():
273 val = float(newtext) * col.units.getConversion()
274 col.instance.setRealValue( val )
275 self.browser.reporter.reportNote("Updated value to %f" % float(newtext))
276 else:
277 self.browser.reporter.reportError("Can't set a FREE variable from the Observer")
278 return
279 self.browser.do_solve_if_auto()
280
281 def sync(self):
282 self.view.queue_draw()
283 #self.browser.reporter.reportNote("SYNC performed")
284
285 def add_instance(self,instance):
286 _col = ObserverColumn(instance,self.colindex,browser=self.browser)
287 self.cols[self.colindex] = _col
288 self.colindex = self.colindex + 1
289
290 # create a new column
291 _renderer = gtk.CellRendererText()
292 _renderer.connect('edited',self.on_view_cell_edited, _col)
293 _tvcol = ClickableTreeColumn(_col.title)
294 _tvcol.pack_start(_renderer,False)
295 _tvcol.set_cell_data_func(_renderer, _col.cellvalue)
296 self.view.append_column(_tvcol);
297 _tvcol.do_connect()
298 #self.browser.reporter.reportError("cols = "+str(self.cols))
299
300 def copy_to_clipboard(self,clip):
301 _s = []
302 _s.append('\t'.join([_v.title for _k,_v in self.cols.iteritems()]))
303 #_cf = [_v.units.getConversion() for _k,_v in self.cols.iteritems()]
304 print "COPYING %d ROWS" % len(self.rows)
305 #print "CONVERSIONS:",_cf
306 for _r in self.rows:
307 _s.append("\t".join([`_v` for _v in _r.get_values(self)]))
308
309 clip.set_text('\n'.join(_s),-1)
310
311 self.browser.reporter.reportNote("Observer '%s' data copied to clipboard" % self.name)

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