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))
예제 #2
0
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)