def test_getHeaders(self): tid = self.create_table() ftc = FeatureTableConnection(client=self.cli, tableName=self.tableName) ftc.openTable(tid) headers = ftc.getHeaders() self.assertEqual(len(headers), 3) self.assertEqual([h.name for h in headers], ['ID', 'a', 'b'])
def test_readSubArray_ordered(self): tid = self.create_table_with_data() ftc = FeatureTableConnection(client=self.cli, tableName=self.tableName) ftc.openTable(tid) can = collections.OrderedDict([(2, [0]), (1, [0,2])]) xs = ftc.readSubArray(can, 0, 4) self.assertEqual(xs[1].values, [[], [1., 3.], [4., 6.], []]) self.assertEqual(xs[0].values, [[7.], [], [8.], []])
def test_readSubArray(self): tid = self.create_table_with_data() ftc = FeatureTableConnection(client=self.cli, tableName=self.tableName) ftc.openTable(tid) can = {1:[0,2], 2:[0]} xs = ftc.readSubArray(can, 0, 4) self.assertEqual(xs[0].values, [[], [1., 3.], [4., 6.], []]) self.assertEqual(xs[1].values, [[7.], [], [8.], []])
def test_isValid(self): tid = self.create_table_with_data() ftc = FeatureTableConnection(client=self.cli, tableName=self.tableName) ftc.openTable(tid) bs = ftc.isValid([2, 0, 1], 0, 4) self.assertEqual(bs[1].values, [True, True, True, True]) self.assertEqual(bs[2].values, [False, True, True, False]) self.assertEqual(bs[0].values, [True, False, True, False])
def test_getRowId(self): tid = self.create_table_with_data() ftc = FeatureTableConnection(client=self.cli, tableName=self.tableName) ftc.openTable(tid) self.assertEqual(ftc.getRowId(1), 0) self.assertEqual(ftc.getRowId(3), 2) self.assertEqual(ftc.getRowId(6), 3) self.assertEqual(ftc.getRowId(8), 1) self.assertIsNone(ftc.getRowId(1000))
def test_createNewTable(self): tid = self.create_table() ftc = FeatureTableConnection(client=self.cli, tableName=self.tableName) ftc.openTable(tid) headers = ftc.table.getHeaders() self.assertEqual(len(headers), 6) self.assertEqual([h.name for h in headers[:3]], ['ID', 'a', 'b']) self.assertEqual([h.name for h in headers[3:]], ['_b_ID', '_b_a', '_b_b'])
def test_readArray(self): tid = self.create_table_with_data() ftc = FeatureTableConnection(client=self.cli, tableName=self.tableName) ftc.openTable(tid) xs = ftc.readArray([0, 2], 0, 3, chunk=2) self.assertEqual(xs[0].values, [1, 8, 3]) self.assertEqual(xs[1].values, [[7.], [], [8.]]) xs = ftc.readArray([2, 0, 1], 0, ftc.getNumberOfRows(), chunk=3) self.assertEqual(xs[1].values, [1, 8, 3, 6]) self.assertEqual(xs[2].values, [[], [1., 2., 3.], [4., 5., 6.], []]) self.assertEqual(xs[0].values, [[7.], [], [8.], []])
def test_addPartialData(self): tid = self.create_table_with_data() ftc = FeatureTableConnection(client=self.cli, tableName=self.tableName) ftc.openTable(tid) cols = ftc.getHeaders() cols = [cols[2], cols[0]] cols[1].values = [2, 4] cols[0].values = [[], [18.]] ftc.addPartialData(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.], [], [], []]) self.assertEqual(xs[2].values, [[7.], [], [8.], [], [], [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)