1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 import csv
35 import StringIO
36 import pyvision as pv
37
39 if val in ("True","False"):
40 return val == "True"
41 try:
42 flt = float(val)
43 except:
44 return val
45
46 if '.' in val:
47 return flt
48 else:
49 return int(round(flt))
50
52 '''
53 Store and manipulate table data
54 '''
55
56 - def __init__(self,filename=None,default_value=None):
57 self.col_headers = []
58 self.col_label = None
59 self.row_headers = []
60 self.row_label = None
61 self.col_format = {}
62 self.hlines = False
63 self.default_value = default_value
64 self.data = {}
65 self.rebuildTable()
66
67 if filename != None:
68 if isinstance(filename,str):
69 f = open(filename,'rb')
70 self.load(f)
71 else:
72
73 self.load(filename)
74
76 reader = csv.reader(f)
77 header=None
78
79 for data in reader:
80 if header == None:
81 header = data
82 assert header[0] == "row"
83 continue
84 assert len(header) == len(data)
85
86 for i in range(1,len(header)):
87 row = convertVal(data[0])
88 col = convertVal(header[i])
89 val = convertVal(data[i])
90
91 self[row,col] = val
92
93
94
95
96
98 self.row_headers.sort(comp_func)
99
100
102 self.col_headers.sort(comp_func)
103
104
106 new_value = self.element(row,col) + value
107 self.setData(row,col,new_value)
108
109
117
120
121 - def setElement(self,row,col,value,accumulate=False):
122 self.setData(row,col,value,accumulate=accumulate)
123
124 - def setData(self,row,col,value,accumulate=False):
125
126 labels_updated = False
127
128 if col not in self.col_headers:
129 self.col_headers.append(col)
130 labels_updated = True
131
132 if row not in self.row_headers:
133 self.row_headers.append(row)
134 labels_updated = True
135
136 if labels_updated:
137 self.rebuildTable()
138
139 self.data[row][col] = value
140
141
143 for row in self.row_headers:
144 if not self.data.has_key(row): self.data[row] = {}
145 for col in self.col_headers:
146 if not self.data[row].has_key(col): self.data[row][col] = self.default_value
147
148
150 return (self.data.has_key(row) and self.data[row].has_key(col))
151
152
154 return self.element(key[0],key[1])
155
157 if self.hasElement(row,col):
158 return self.data[row][col]
159 else:
160 return self.default_value
161
162 - def elementAsText(self,row,col):
163 if isinstance(self.col_format,str):
164 return self.col_format%self.element(row,col)
165 if isinstance(self.col_format,dict) and self.col_format.has_key(col):
166 return self.col_format[col]%self.element(row,col)
167
168
169
170 return "%s"%(self.element(row,col),)
171
172 - def justifyText(self,text,width,side='l'):
173 assert side in ['c','l','r']
174 l = len(text)
175 if l > width:
176 return text[:width]
177 else:
178 pad = width - l
179 if side=='c':
180 front = " "*(pad/2)
181 back = " "*(pad - pad/2)
182 return front + text + back
183 elif side=='r':
184 return " "*pad + text
185 else:
186 return text + " "*pad
187
188 return text
189
190 - def asHtml(self, print_col_headers = True, print_row_headers = False, equal_cols = False, style='simple'):
191 result = "<TABLE CELLPADDING=6 CELLSPACING=0>\n"
192 result += ' <TR BGCOLOR="#D3C6AD">\n'
193 result += ' '
194 if print_row_headers:
195 result += '<TD ALIGN=LEFT></TD>'
196
197 for col in self.col_headers:
198 result += '<TH>%s</TH>'%col
199 result += '\n'
200 result += ' </TR>\n'
201
202 i = 0
203 for row in self.row_headers:
204 bgcolor = '#FBEBCE'
205 if i % 2 == 1:
206 bgcolor = '#EFE0C4'
207 result += ' <TR BGCOLOR="%s">\n'%bgcolor
208 result += ' '
209 if print_row_headers:
210 result += '<TD ALIGN=LEFT>%s</TD>'%(row,)
211 for col in self.col_headers:
212 align = 'LEFT'
213 try:
214
215 val = float(self[row,col])
216 align = 'RIGHT'
217 except:
218
219 pass
220
221 val = self.elementAsText(row,col)
222 result += '<TD ALIGN=%s>%s</TD>'%(align,val)
223 result += '\n'
224 result += ' </TR>\n'
225 i += 1
226 result += "</TABLE>\n"
227 return result
228
229
230
231 - def asPlainText(self, print_col_headers = True, print_row_headers = True, equal_cols = False, separator="|"):
232 '''Returns a text string which is a formated table.'''
233 assert len(separator) == 1
234
235 rows = self.row_headers
236 cols = self.col_headers
237
238 col_widths = {}
239 for col in self.col_headers:
240 if print_col_headers:
241 col_widths[col] = len(str(col))
242 else:
243 col_widths[col] = 0
244 for row in self.row_headers:
245 w = len(self.elementAsText(row,col))
246 if w > col_widths[col]:
247 col_widths[col] = w
248 if equal_cols:
249
250 max_width = 0
251 for key,value in col_widths.iteritems():
252 max_width = max(max_width,value)
253 for key in col_widths.keys():
254 col_widths[key]=max_width
255
256 row_header_width = 0
257 for row in rows:
258 row_header_width = max(row_header_width,len(str(row)))
259
260
261 out = ""
262
263
264 if print_row_headers:
265 out += "|" + "-"*(row_header_width+2)
266 out += "|"
267 for col in cols:
268 out += "-"*(col_widths[col]+2)+"|"
269 out = out[:-1]
270 out += "|\n"
271
272 if print_col_headers:
273 out += "|"
274 if print_row_headers:
275 out += " "*(row_header_width+2)+"|"
276 for col in cols:
277 text = self.justifyText(str(col),col_widths[col],'l')
278 out += " "+text+" |"
279 out = out[:-1]
280 out += "|\n"
281
282
283 if print_row_headers:
284 out += "|" + "-"*(row_header_width+2)
285 out += "|"
286 for col in cols:
287 out += "-"*(col_widths[col]+2)+"|"
288 out = out[:-1]
289 out += "|\n"
290
291 for row in rows:
292 out +="|"
293 if print_row_headers:
294 out += " " + self.justifyText(str(row),row_header_width,'l')+" |"
295 for col in cols:
296 text = self.elementAsText(row,col)
297 try:
298
299 val = float(text)
300
301 text = self.justifyText(text,col_widths[col],'r')
302 except:
303
304 text = self.justifyText(text,col_widths[col],'l')
305 assert len(text) == col_widths[col]
306 out += " "+text+" "+separator
307
308 out = out[:-1]
309 out += "|\n"
310
311
312 if print_row_headers:
313 out += "|" + "-"*(row_header_width+2)
314 out += "|"
315 for col in cols:
316 out += "-"*(col_widths[col]+2)+"|"
317 out = out[:-1]
318 out += "|\n"
319
320 return out
321
322
323
324
325
327 return len(self.row_headers)
328
330 return len(self.col_headers)
331
332
334 '''Returns a text string which as a table formated for latex'''
335
337 '''Returns the table data as a list of lists'''
338 rows = self.row_headers
339 cols = self.col_headers
340
341 result = []
342
343 if headers:
344 tmp = ['row']
345 for col in cols:
346 tmp.append(col)
347 result.append(tmp)
348
349 for row in rows:
350 tmp = []
351 if headers:
352 tmp.append(row)
353 for col in cols:
354 tmp.append(self.element(row,col))
355 result.append(tmp)
356
357 return result
358
359
360 - def head(self,N=10):
361 '''Returns a table from the first N rows.'''
362 rows = self.row_headers
363 cols = self.col_headers
364
365 result = pv.Table()
366
367 for row in rows[:N]:
368 for col in cols:
369 result[row,col] = self[row,col]
370
371 return result
372
373
374 - def tail(self,N=10):
375 '''Returns a table from the last N rows.'''
376 rows = self.row_headers
377 cols = self.col_headers
378
379 result = pv.Table()
380
381 for row in rows[-N:]:
382 for col in cols:
383 result[row,col] = self[row,col]
384
385 return result
386
387
388 - def save(self,filename,headers=True):
389 '''Save the table to CSV'''
390 if isinstance(filename,str):
391 f = open(filename,'wb')
392 else:
393 f = filename
394 writer = csv.writer(f)
395 writer.writerows(self.asLists(headers=headers))
396
399
400
401 import unittest
404 color = Table(default_value=0)
405 color.accumulateData('red','red',1)
406 color.accumulateData('red','red',1)
407 color.accumulateData('red','red',1)
408 color.accumulateData('blue','blue',1)
409 color.accumulateData('blue','blue',1)
410 color.accumulateData('blue','blue',1)
411 color.accumulateData('blue','blue',1)
412 color.accumulateData('pink','pink',1)
413 color.accumulateData('pink','pink',1)
414 color.accumulateData('pink','pink',1)
415 color.accumulateData('pink','pink',1)
416 color.accumulateData('pink','pink',1)
417 color.accumulateData('pink','red',1)
418 color.accumulateData('pink','red',1)
419 color.accumulateData('blue','red',1)
420 color.accumulateData('blue','red',1)
421 color.accumulateData('red','blue',1)
422 color.accumulateData('green','green',1)
423 color.accumulateData('red','green',1)
424 self.color = color
425
426
427
428
429 sim_face = Table(default_value=0)
430 sim_face.setData('accept','accept',900)
431 sim_face.setData('reject','reject',998001)
432 sim_face.setData('accept','reject',100)
433 sim_face.setData('reject','accept',999)
434 self.sim_face = sim_face
435
440
443
445 expected = 'row,red,blue,pink,green\r\nred,3,1,0,1\r\nblue,2,4,0,0\r\npink,2,0,5,0\r\ngreen,0,0,0,1\r\n'
446 output = StringIO.StringIO()
447 self.color.save(output)
448 self.assertEqual(output.getvalue(),expected)
449
450 expected = '3,1,0,1\r\n2,4,0,0\r\n2,0,5,0\r\n0,0,0,1\r\n'
451 output = StringIO.StringIO()
452 self.color.save(output,headers=False)
453 self.assertEqual(output.getvalue(),expected)
454
457
459 tab = Table()
460
461 tab[2,1] = 'b'
462 tab[1,1] = 'a'
463 tab[3,1] = 'c'
464
465
466 tab.sortByRowHeader()
467
468