def create_table_with_data(self): cli, sess = self.create_client() ftc = FeatureTableConnection(client=cli, tableName=self.tableName) desc = [('a', 3), ('b', 1)] ftc.createNewTable('ID', desc) cols = ftc.getHeaders() cols[0].values = [1, 8, 3, 6] cols[1].values = [[], [1., 2., 3.], [4., 5., 6.], []] cols[2].values = [[7.], [], [8.], []] ftc.addData(cols) tid = ftc.tableId ftc.close() return tid
def test_addData(self): tid = self.create_table_with_data() ftc = FeatureTableConnection(client=self.cli, tableName=self.tableName) ftc.openTable(tid) cols = ftc.getHeaders() cols[0].values = [2, 4] cols[1].values = [[11., 12., 13.], [14., 15., 16.]] cols[2].values = [[17.], [18.]] ftc.addData(cols) xs = ftc.readArray(range(len(ftc.getHeaders())), 0, ftc.getNumberOfRows(), chunk=4) self.assertEqual(xs[0].values, [1, 8, 3, 6, 2, 4]) self.assertEqual(xs[1].values, [[], [1., 2., 3.], [4., 5., 6.], [], [11., 12., 13.], [14., 15., 16.]]) self.assertEqual(xs[2].values, [[7.], [], [8.], [], [17.], [18.]])
class FeatureTable(object): def __init__(self, client, tableName): self.tc = FeatureTableConnection(client=client, tableName=tableName) self.versiontag = None def close(self): self.tc.close(False) @property def conn(self): return self.tc.conn def createTable(self, featureNames, version): """ Initialise an OMERO.table for storing features @param featureNames Either a mapping of feature names to feature sizes, or a list of single value feature names which can be parsed using parseFeatureName """ # Unparsed list or dict? if hasattr(featureNames, 'keys'): features = featureNames else: features = featureSizes(featureNames) colNames = sorted(features.keys()) desc = [(name, features[name]) for name in colNames] self.tc.createNewTable('id', desc) self.versiontag = getVersionAnnotation(self.conn, version) if not self.versiontag: self.versiontag = createVersionAnnotation(self.conn, version) addTagTo(self.conn, self.versiontag, 'OriginalFile', self.tc.tableId) # TODO: There's a bug or race condition somewhere which means this # annotation may be lost. Closing and reopening the table seems to # avoid this. tid = self.tc.tableId self.close() self.openTable(tid, version) def openTable(self, tableId, version=None): try: vertag = getVersion(self.conn, 'OriginalFile', tableId) if not vertag: raise WndcharmStorageError( 'Table id %d has no version tag' % tableId) if version is not None: assertVersionMatch(version, vertag, 'table:%d' % tableId) self.tc.openTable(tableId) self.versiontag = vertag return True except TableConnectionError as e: print "No table found: %s" % e return False def isTableCompatible(self, features): """ Check whether an existing table is compatible with this set of features, that is whether suitable columns exist @return true if this set of features can be stored in this table """ cols = self.tc.getHeaders() colMap = dict([(c.name, c) for c in cols]) featSizes = featureSizes(features.names) for (ft, sz) in featSizes.iteritems(): if (ft not in colMap or colMap[ft].size != sz): print '%s [%d] is incompatible' % (ft, sz) return False return True def tableContainsId(self, id): """ Check whether this ID is already present in the table """ return self.tc.getRowId(id) is not None def saveFeatures(self, id, features): """ Save the features to a table @param features an object with field names holding a list of single value feature names, and values holding a list of doubles corresponding to names """ cols = self.tc.getHeaders() colMap = dict([(c.name, c) for c in cols]) cols[0].values = [id] for (name, value) in izip(features.names, features.values): ft, idx = parseFeatureName(name) col = colMap[ft] if not col.values: col.values = [[float('nan')] * col.size] col.values[0][idx] = value self.tc.addData(cols) def loadFeatures(self, id): """ Load features for an object from a table @return a (names, values) tuple where names is a list of single value features and value are the corresponding feature values """ r = self.tc.getRowId(id) # Skip the first id column colNumbers = range(1, len(self.tc.getHeaders())) cols = self.tc.readArray(colNumbers, r, r + 1) names = [] values = [] for col in cols: names.extend([createFeatureName(col.name, x) for x in xrange(col.size)]) values.extend(col.values[0]) return (names, values) def bulkLoadFeatures(self): """ Load features for all objects in a table @return a (names, values, ids) tuple where names is a list of single value features, values is a list of lists of the corresponding feature values and ids is a list of object IDs. In other words values[i] is the list of feature values corresponding to object with ID given by ids[i]. """ colNumbers = range(len(self.tc.getHeaders())) nr = self.tc.getNumberOfRows() cols = self.tc.readArray(colNumbers, 0, nr, CHUNK_SIZE) names = [] ids = cols[0].values for col in cols[1:]: names.extend([createFeatureName(col.name, x) for x in xrange(col.size)]) values = map(lambda *args: list(chain.from_iterable(args)), *[c.values for c in cols[1:]]) return (names, values, ids)