1
2
3 """
4 ::
5 /*
6 * $Id$
7 *
8 * Copyright 2009 Glencoe Software, Inc. All rights reserved.
9 * Use is subject to license terms supplied in LICENSE.txt
10 *
11 */
12 """
13
14 """
15 Concrete implementations of the omero.grid.Column
16 type hierarchy which know how to convert themselves
17 to PyTables types.
18 """
19
20 import omero, Ice, IceImport
21 IceImport.load("omero_Tables_ice")
22
23 try:
24 import numpy
25 tables = __import__("tables")
26 has_pytables = True
27 except ImportError:
28 has_pytables = False
29
30
32 """
33 Takes a list of columns and converts them into a map
34 from names to tables.* column descriptors
35 """
36 definition = {}
37 for i in range(len(cols)):
38 column = cols[i]
39 instance = column.descriptor(pos=i)
40 if column.name in definition:
41 raise omero.ApiUsageException(
42 None, None, "Duplicate column name: %s" % column.name)
43 definition[column.name] = instance
44
45 return definition
46
48 """
49 Base logic for all columns
50 """
51
53
54
55 d = self.descriptor(None)
56 if isinstance(d, tables.IsDescription):
57 cols = d.columns
58 try:
59 del cols["_v_pos"]
60 except KeyError:
61 pass
62 self._types = [None] * len(cols)
63 self._subnames = [None] * len(cols)
64 for k, v in cols.items():
65 self._types[v._v_pos] = v.recarrtype
66 self._subnames[v._v_pos] = "/" + k
67
68 else:
69 self._types = [d.recarrtype]
70 self._subnames = [""]
71
73 """
74 Called by tables.py when first initializing columns.
75 Can be used to complete further initialization.
76 """
77 self.__table = tbl
78
80 """
81 Called by tables.py to give columns. By default, does nothing.
82 """
83 pass
84
91
92 - def read(self, tbl, start, stop):
95
97 """
98 Any method which does not use the "values" field
99 will need to override this method.
100 """
101 if self.values is None:
102 return None
103 else:
104 return len(self.values)
105
107 """
108 Any method which does not use the "values" field
109 will need to override this method.
110 """
111 if size is None:
112 self.values = None
113 else:
114 self.values = [None for x in range(size)]
115
117 """
118 Any method which does not use the "values" field
119 will need to override this method.
120 """
121 return [self.values]
122
124 """
125 Override this method if descriptor() doesn't return the correct data
126 type/size at initialisation- this is mostly a problem for array types
127 """
128 names = [self.name + sn for sn in self._subnames]
129 return zip(names, self._types)
130
132 """
133 Any method which does not use the "values" field
134 will need to override this method.
135 """
136 self.values = rows[self.name]
137
138
139
140
141
142
143
144 self.values = self.values.tolist()
145
146 -class FileColumnI(AbstractColumn, omero.grid.FileColumn):
147
148 - def __init__(self, name = "Unknown", *args):
151
153 return tables.Int64Col(pos=pos)
154
156
157 - def __init__(self, name = "Unknown", *args):
160
162 return tables.Int64Col(pos=pos)
163
164 -class WellColumnI(AbstractColumn, omero.grid.WellColumn):
165
166 - def __init__(self, name = "Unknown", *args):
169
171 return tables.Int64Col(pos=pos)
172
174
175 - def __init__(self, name = "Unknown", *args):
178
180 return tables.Int64Col(pos=pos)
181
182 -class RoiColumnI(AbstractColumn, omero.grid.RoiColumn):
183
184 - def __init__(self, name = "Unknown", *args):
187
189 return tables.Int64Col(pos=pos)
190
191 -class BoolColumnI(AbstractColumn, omero.grid.BoolColumn):
192
193 - def __init__(self, name = "Unknown", *args):
196
198 return tables.BoolCol(pos=pos)
199
201
202 - def __init__(self, name = "Unknown", *args):
205
207 return tables.Float64Col(pos=pos)
208
209 -class LongColumnI(AbstractColumn, omero.grid.LongColumn):
210
211 - def __init__(self, name = "Unknown", *args):
214
216 return tables.Int64Col(pos=pos)
217
219
220 - def __init__(self, name = "Unknown", *args):
223
227
229 """
230 Check for strings longer than the initialised column width
231 """
232 for v in self.values:
233 if len(v) > self.size:
234 raise omero.ValidationException(
235 None, None, "Maximum string length in column %s is %d" %
236 (self.name, self.size))
237 return [self.values]
238
240 """
241 Overriding to correct for size.
242 (Testing suggests this may not be necessary, the size appears to be
243 correctly set at initialisation)
244 """
245 return [(self.name, "S", self.size)]
246
248
249
250 if pos is None:
251 return tables.StringCol(pos=pos, itemsize=1)
252 if self.size < 1:
253 raise omero.ApiUsageException(
254 None, None, "String size must be > 0 (Column: %s)" % self.name)
255 return tables.StringCol(pos=pos, itemsize=self.size)
256
258 """
259 Additional base logic for array columns
260 """
261
264
266 AbstractColumn.settable(self, tbl)
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282 column = getattr(tbl.cols, self.name)
283 self.size = column.descr._v_dtypes[column.name].shape[0]
284
285
287 """
288 Arrays of size 1 have to be converted to scalars, otherwise the
289 column-to-row conversion in HdfStorage.append() will fail.
290 This is messy, but I can't think of a better way.
291 """
292 for v in self.values:
293 if len(v) != self.size:
294 raise omero.ValidationException(
295 None, None, "Column %s requires arrays of length %d" %
296 (self.name, self.size))
297
298 if self.size == 1:
299 return [[v[0] for v in self.values]]
300 return [self.values]
301
303 """
304 Overriding to correct for size.
305 """
306 return [(self.name, self._types[0], self.size)]
307
309
310 - def __init__(self, name = "Unknown", *args):
313
315
316 if pos is None:
317 return tables.Float32Col(pos=pos)
318 if self.size < 1:
319 raise omero.ApiUsageException(
320 None, None, "Array length must be > 0 (Column: %s)" % self.name)
321 return tables.Float32Col(pos=pos, shape=self.size)
322
324
325 - def __init__(self, name = "Unknown", *args):
328
330
331 if pos is None:
332 return tables.Float64Col(pos=pos)
333 if self.size < 1:
334 raise omero.ApiUsageException(
335 None, None, "Array length must be > 0 (Column: %s)" % self.name)
336 return tables.Float64Col(pos=pos, shape=self.size)
337
339
340 - def __init__(self, name = "Unknown", *args):
343
345
346 if pos is None:
347 return tables.Int64Col(pos=pos)
348 if self.size < 1:
349 raise omero.ApiUsageException(
350 None, None, "Array length must be > 0 (Column: %s)" % self.name)
351 return tables.Int64Col(pos=pos, shape=self.size)
352
353 -class MaskColumnI(AbstractColumn, omero.grid.MaskColumn):
354
355 - def __init__(self, name = "Unknown", *args):
358
360 if a is None:
361 if b is None:
362 return
363
364 if b is not None:
365 if len(a) == len(b):
366 return
367 raise omero.ValidationException(None, None, "Columns don't match")
368
377
379 class MaskDescription(tables.IsDescription):
380 _v_pos = pos
381 i = tables.Int64Col(pos=0)
382 z = tables.Int32Col(pos=1)
383 t = tables.Int32Col(pos=2)
384 x = tables.Float64Col(pos=3)
385 y = tables.Float64Col(pos=4)
386 w = tables.Float64Col(pos=5)
387 h = tables.Float64Col(pos=6)
388 return MaskDescription()
389
391 self.__sanitycheck()
392 a = [
393 self.imageId,
394 self.theZ,
395 self.theT,
396 self.x,
397 self.y,
398 self.w,
399 self.h,
400 ]
401 return a
402
404 self.__sanitycheck()
405 if self.imageId is None:
406 return None
407 else:
408 return len(self.imageId)
409
411 if size is None:
412 self.imageId = None
413 self.theZ = None
414 self.theT = None
415 self.x = None
416 self.y = None
417 self.w = None
418 self.h = None
419 else:
420 dts = self.dtypes()
421 self.imageId = numpy.zeroes(size, dtype = dts[0])
422 self.theZ = numpy.zeroes(size, dtype = dts[1])
423 self.theT = numpy.zeroes(size, dtype = dts[2])
424 self.x = numpy.zeroes(size, dtype = dts[3])
425 self.y = numpy.zeroes(size, dtype = dts[4])
426 self.w = numpy.zeroes(size, dtype = dts[5])
427 self.h = numpy.zeroes(size, dtype = dts[6])
428
436
437 - def read(self, tbl, start, stop):
443
445 self.bytes = []
446 for idx in rowNumbers:
447 self.bytes.append(masks[idx].tolist())
448
450 rows = all_rows[self.name]
451
452 self.imageId = rows["i"].tolist()
453 self.theZ = rows["z"].tolist()
454 self.theT = rows["t"].tolist()
455 self.x = rows["x"]
456 self.y = rows["y"]
457 self.w = rows["w"]
458 self.h = rows["h"]
459
469
471 n = tbl._v_name
472 f = tbl._v_file
473 p = tbl._v_parent
474
475
476 try:
477 masks = getattr(p, "%s_masks" % n)
478 except tables.NoSuchNodeError:
479 masks = f.createVLArray(p, "%s_masks" % n, tables.UInt8Atom())
480 return masks
481
482
483
484
485
486
488
490 self.id = cls.ice_staticId()
491 self.f = f
492
495
498
500 ic.addObjectFactory(self, self.id)
501
502
503
504
505
506 ObjectFactories = {
507 FileColumnI: ObjectFactory(FileColumnI, lambda: FileColumnI()),
508 ImageColumnI: ObjectFactory(ImageColumnI, lambda: ImageColumnI()),
509 RoiColumnI: ObjectFactory(RoiColumnI, lambda: RoiColumnI()),
510 WellColumnI: ObjectFactory(WellColumnI, lambda: WellColumnI()),
511 PlateColumnI: ObjectFactory(PlateColumnI, lambda: PlateColumnI()),
512 BoolColumnI: ObjectFactory(BoolColumnI, lambda: BoolColumnI()),
513 DoubleColumnI: ObjectFactory(DoubleColumnI, lambda: DoubleColumnI()),
514 LongColumnI: ObjectFactory(LongColumnI, lambda: LongColumnI()),
515 StringColumnI: ObjectFactory(StringColumnI, lambda: StringColumnI()),
516 FloatArrayColumnI: ObjectFactory(FloatArrayColumnI, lambda: FloatArrayColumnI()),
517 DoubleArrayColumnI: ObjectFactory(DoubleArrayColumnI, lambda: DoubleArrayColumnI()),
518 LongArrayColumnI: ObjectFactory(LongArrayColumnI, lambda: LongArrayColumnI()),
519 MaskColumnI: ObjectFactory(MaskColumnI, lambda: MaskColumnI())
520 }
521