Mercurial > hg > audiodb
changeset 717:159becb0701e
the access level wrapper now exposes the python native data insert.
there's a nasty segfault to track though...
author | map01bf |
---|---|
date | Wed, 23 Jun 2010 17:52:30 +0000 |
parents | 26a19beb7e3d |
children | 14568e432e73 |
files | bindings/python/README.txt bindings/python/pyadb.py bindings/python/pyadbmodule.c bindings/python/setup.py bindings/python/tests/InitialisationRelated.py |
diffstat | 5 files changed, 40 insertions(+), 28 deletions(-) [+] |
line wrap: on
line diff
--- a/bindings/python/README.txt Wed Jun 23 10:12:24 2010 +0000 +++ b/bindings/python/README.txt Wed Jun 23 17:52:30 2010 +0000 @@ -7,20 +7,10 @@ Notes: - a compatible build of audioDB (>=r914) needs to be linkable at runtime - - currently only the direct C-api exposure layer is visible, so the calling semantics are a bit gross + - a basic database instance-centric class structure is available via pyadb.py, use this not _pyadb (the direct C interface) + - the unit tests ( in test/InitialisationRelated.py) show basic functionality... -The actual query call is a bit of a mess, but will be more intuitive from the native python layer (to be written)... -so the python bindings now have a complete path: - >>import _pyadb - >>aDB = _pyadb._pyadb_create("test.adb", 0,0,0) - >>_pyadb._pyadb_status(aDB) - >>_pyadb._pyadb_insertFromFile(aDB, "someFeats.mfcc12") - ...(add some more data) - >>result = _pyadb._pyadb_queryFromKey(aDB, "a Key in aDB", [options]) - - and then result has a nice dict of your results. - -21 September 2009, Ben Fields, b.fields@gold.ac.uk \ No newline at end of file +Updated 23 June 2009, Ben Fields, b.fields@gold.ac.uk \ No newline at end of file
--- a/bindings/python/pyadb.py Wed Jun 23 10:12:24 2010 +0000 +++ b/bindings/python/pyadb.py Wed Jun 23 17:52:30 2010 +0000 @@ -16,10 +16,10 @@ import unittest import _pyadb -ADB_HEADER_FLAG_L2NORM = 0x1#annoyingly I can't find a means -ADB_HEADER_FLAG_POWER = 0x4#around defining these flag definitions -ADB_HEADER_FLAG_TIMES = 0x20#as they aren't even exported to the -ADB_HEADER_FLAG_REFERENCES = 0x40#api, so this is the only way to get them. +ADB_HEADER_FLAG_L2NORM = 0x1 #annoyingly I can't find a means +ADB_HEADER_FLAG_POWER = 0x4 #around defining these flag definitions +ADB_HEADER_FLAG_TIMES = 0x20 #as they aren't even exported to the +ADB_HEADER_FLAG_REFERENCES = 0x40 #api, so this is the only way to get them. class Usage(Exception): """error to indicate that a method has been called with incorrect args""" @@ -45,7 +45,10 @@ return def insert(self, featFile=None, powerFile=None, timesFile=None, featData=None, powerData=None, timesData=None, key=None): - """Insert features into database. Can be done with data provided directly or by giving a path to a binary fftExtract style feature file. If power and/or timing is engaged in the database header, it must be provided (via the same means as the feature) or a Usage exception will be raised. Power files should be of the same binary type as features. Times files should be the ascii number length of time in seconds from the begining of the file to segment start, one per line.\n---Note that direct data insertion is not yet implemented.---""" + """ + Insert features into database. Can be done with data provided directly or by giving a path to a binary fftExtract style feature file. If power and/or timing is engaged in the database header, it must be provided (via the same means as the feature) or a Usage exception will be raised. Power files should be of the same binary type as features. Times files should be the ascii number length of time in seconds from the begining of the file to segment start, one per line. + If providing data directly, featData should be a numpy array with shape= (number of Dimensions, number of Vectors) + """ #While python style normally advocates leaping before looking, these check are nessecary as #it is very difficult to assertain why the insertion failed once it has been called. if (self.hasPower and (((featFile) and powerFile==None) or ((featData) and powerData==None))): @@ -57,7 +60,7 @@ args = {"db":self._db} if featFile: args["features"] = featFile - elif featData: + elif (featData != None): args["features"] = featData else: raise(Usage, "Must provide some feature data!") @@ -75,12 +78,20 @@ args["key"]=str(key) if featFile: if not _pyadb._pyadb_insertFromFile(**args): - raise(RuntimeError, "Insertion failed for an unknown reason.") + raise(RuntimeError, "Insertion from file failed for an unknown reason.") else: self._updateDBAttributes() return - elif featData: - raise(NotImplementedError, "direct data insertion not yet implemented") + elif (featData != None): + if (len(args["features"].shape) == 1) : args["features"] = args["features"].reshape((args["features"].shape[0],1)) + args["nDim"], args["nVect"] = args["features"].shape + args["features"] = args["features"].flatten() + print "args: " + str(args) + if not _pyadb._pyadb_insertFromArray(**args): + raise(RuntimeError, "Direct data insertion failed for an unknown reason.") + else: + self._updateDBAttributes() + return def configCheck(self, scrub=False): """examine self.configQuery dict. For each key encouters confirm it is in the validConfigTerms list and if appropriate, type check. If scrub is False, leave unexpected keys and values alone and return False, if scrub try to correct errors (attempt type casts and remove unexpected entries) and continue. If self.configQuery only contains expected keys with correctly typed values, return True. See Pyadb.validConfigTerms for allowed keys and types. Note also that include/exclude key lists memebers or string switched are not verified here, but rather when they are converted to const char * in the C api call and if malformed, an error will be rasied from there. Valid keys and values in queryconfig:
--- a/bindings/python/pyadbmodule.c Wed Jun 23 10:12:24 2010 +0000 +++ b/bindings/python/pyadbmodule.c Wed Jun 23 17:52:30 2010 +0000 @@ -152,14 +152,14 @@ unsigned int nDims = 0; unsigned int nVect = 0; PyObject *incoming = 0; - PyObject *features = 0; + PyObject *features = NULL; PyObject *power = NULL; const char *key = NULL; PyObject *times = NULL; PyArray_Descr *descr; static char *kwlist[] = { "db", "features", "nDim", "nVect", "power", "key", "times" , NULL}; - ok = PyArg_ParseTupleAndKeywords(args, keywds, "OOII|OsO", kwlist, &incoming, &features, nDims, nVect, &power, &key, ×); + ok = PyArg_ParseTupleAndKeywords(args, keywds, "OOII|OsO", kwlist, &incoming, &features, &nDims, &nVect, &power, &key, ×); if (!ok){return NULL;} //check our arrays if (!PyArray_Check(features)){
--- a/bindings/python/setup.py Wed Jun 23 10:12:24 2010 +0000 +++ b/bindings/python/setup.py Wed Jun 23 17:52:30 2010 +0000 @@ -26,7 +26,7 @@ module1 = Extension('_pyadb', define_macros = [('MAJOR_VERSION', '0'), - ('MINOR_VERSION', '1')], + ('MINOR_VERSION', '2')], include_dirs = ['/opt/local/include', '../../', join(numpyBase[0],'core/include')], libraries = ['audioDB'], library_dirs = ['../../', '/opt/local/lib'], @@ -34,7 +34,7 @@ setup (name = 'pyadb', - version = '0.1a', + version = '0.2a', description = 'AudioDB is a vector based similiarity and matching tool.', maintainer = 'Benjamin Fields', maintainer_email = 'b.fields@gold.ac.uk',
--- a/bindings/python/tests/InitialisationRelated.py Wed Jun 23 10:12:24 2010 +0000 +++ b/bindings/python/tests/InitialisationRelated.py Wed Jun 23 17:52:30 2010 +0000 @@ -13,6 +13,7 @@ import sys import os,os.path import pyadb +import numpy as np import struct import unittest @@ -28,7 +29,7 @@ self.adb.status() except: self.assert_(False) - def test_1DinsertionSelfQuery(self): + def test_1DinsertionFromFileSelfQuery(self): tH = open("testfeature", 'w') tH.write(struct.pack("=id",1,1)) tH.close() @@ -39,7 +40,17 @@ self.assert_(result.rawData.has_key("testfeature")) self.assert_(len(result.rawData["testfeature"]) == 1) self.assert_(result.rawData["testfeature"][0] == (float("-inf"), 0,0)) - + os.remove(self.adb.path)#delete the db + def test_1DinsertionFromArraySelfQuery(self): + test1 = np.ones(6) + print "test1: " + str(test1) + self.adb.insert(featData=test1, key="testfeature") + self.adb.configQuery["seqLength"] = 1 + result = self.adb.query(key="testfeature") + self.assert_(len(result.rawData) == 1) + self.assert_(result.rawData.has_key("testfeature")) + self.assert_(len(result.rawData["testfeature"]) == 1) + self.assert_(result.rawData["testfeature"][0] == (float("-inf"), 0,0))