annotate bindings/python/pyadbmodule.c @ 624:afa05407ce41

added a bunch of improved error messaging. added another parameter the query call (I know, too many already) to specify the desired format of the output result object (keyword dict or ordered list).
author map01bf
date Mon, 21 Sep 2009 23:10:57 +0000
parents 695651b8c1a3
children 356d7b319ae8
rev   line source
map01bf@620 1 // pyadbmodule.c
map01bf@620 2 //
map01bf@620 3 // the internal portion of the wrapper for audio
map01bf@620 4 // see pyadb.py for the public classes
map01bf@620 5 //
map01bf@620 6 // Created by Benjamin Fields on 2009-09-04.
map01bf@621 7 // Copyright (c) 2009 Goldsmith University of London.
map01bf@621 8 // Distributed and licensed under GPL2. See ../../license.txt for details.
map01bf@620 9 //
map01bf@620 10 #include <fcntl.h>
map01bf@621 11 #include <string.h>
map01bf@620 12 #include "Python.h"
map01bf@622 13 #include "structmember.h"
map01bf@620 14 #include "audioDB_API.h"
map01bf@620 15 #include "numpy/arrayobject.h"
map01bf@620 16
map01bf@620 17 static void _pyadb_close(void *ptr);
map01bf@620 18
map01bf@620 19
map01bf@620 20 /* create a new database */
map01bf@620 21 /* returns a struct or NULL on failure */
map01bf@620 22 /* api call: */
map01bf@620 23 /* adb_ptr audiodb_create(const char *path, unsigned datasize, unsigned ntracks, unsigned datadim);*/
map01bf@620 24 PyObject * _pyadb_create(PyObject *self, PyObject *args)
map01bf@620 25 {
map01bf@620 26 unsigned datasize, ntracks, datadim;
map01bf@620 27 const char *path;
map01bf@620 28 int ok;
map01bf@620 29 adb_ptr new_database;
map01bf@620 30 ok = PyArg_ParseTuple(args, "sIII", &path, &datasize, &ntracks, &datadim);
map01bf@620 31 if (!ok) return 0;
map01bf@620 32 new_database = audiodb_create(path, datasize, ntracks, datadim);
map01bf@620 33 if (!new_database) return 0;
map01bf@620 34
map01bf@620 35 return PyCObject_FromVoidPtr( new_database, _pyadb_close);
map01bf@620 36 }
map01bf@620 37
map01bf@620 38 /* open an existing database */
map01bf@620 39 /* returns a struct or NULL on failure */
map01bf@620 40 /* flags expects fcntl flags concerning the opening mode */
map01bf@620 41 /* api call: */
map01bf@620 42 // adb_ptr audiodb_open(const char *path, int flags);
map01bf@620 43 PyObject * _pyadb_open(PyObject *self, PyObject *args)
map01bf@620 44 {
map01bf@620 45 const char *path;
map01bf@620 46 char mode;
map01bf@620 47 int ok;//in python layer need to translate boolean flags to byte mask
map01bf@620 48 adb_ptr fresh_database;
map01bf@620 49 ok = PyArg_ParseTuple(args, "sc", &path, &mode);
map01bf@620 50 if (!ok) return 0;
map01bf@620 51 if (mode == 'r'){
map01bf@620 52 fresh_database = audiodb_open(path, O_RDONLY);
map01bf@620 53 }else if (mode == 'w'){
map01bf@620 54 fresh_database = audiodb_open(path, O_RDWR);
map01bf@620 55 }else{
map01bf@620 56 PyErr_SetString(PyExc_ValueError,
map01bf@620 57 "mode must be either \'r\' or \'w\'. It appears to be something else.");
map01bf@620 58 return 0;
map01bf@620 59 }
map01bf@620 60 if (!fresh_database) return 0;
map01bf@620 61
map01bf@620 62 return PyCObject_FromVoidPtr( fresh_database, _pyadb_close);
map01bf@620 63 }
map01bf@620 64
map01bf@620 65 /* database status */
map01bf@620 66 /* api call: */
map01bf@620 67 // int audiodb_status(adb_ptr mydb, adb_status_ptr status);
map01bf@620 68 PyObject * _pyadb_status(PyObject *self, PyObject *args)
map01bf@620 69 {
map01bf@620 70 adb_ptr check_db;
map01bf@620 71 adb_status_ptr status;
map01bf@620 72 int flags, ok;
map01bf@620 73 PyObject * incoming = 0;
map01bf@620 74 status = (adb_status_ptr)malloc(sizeof(struct adbstatus));
map01bf@620 75
map01bf@620 76 ok = PyArg_ParseTuple(args, "O", &incoming);
map01bf@620 77 if (!ok) return 0;
map01bf@620 78 check_db = (adb_ptr)PyCObject_AsVoidPtr(incoming);
map01bf@620 79
map01bf@620 80
map01bf@620 81 flags = audiodb_status(check_db, status);
map01bf@620 82 return Py_BuildValue("IIIIILL", status->numFiles,
map01bf@620 83 status->dim,
map01bf@620 84 status->dudCount,
map01bf@620 85 status->nullCount,
map01bf@620 86 status->flags,
map01bf@620 87 status->length,
map01bf@620 88 status->data_region_size);
map01bf@620 89
map01bf@620 90 }
map01bf@620 91
map01bf@620 92 /*engage l2norm in the referenced db*/
map01bf@620 93 /*api call:*/
map01bf@620 94 //int audiodb_l2norm(adb_ptr mydb);
map01bf@620 95 PyObject * _pyadb_l2norm(PyObject *self, PyObject *args)
map01bf@620 96 {
map01bf@620 97 adb_ptr current_db;
map01bf@620 98 int ok;
map01bf@620 99 PyObject * incoming = 0;
map01bf@620 100
map01bf@620 101 ok = PyArg_ParseTuple(args, "O", &incoming);
map01bf@620 102 if (!ok) return 0;
map01bf@620 103 current_db = (adb_ptr)PyCObject_AsVoidPtr(incoming);
map01bf@620 104
map01bf@620 105 ok = audiodb_l2norm(current_db);
map01bf@622 106 return PyBool_FromLong(ok-1);
map01bf@620 107
map01bf@620 108 }
map01bf@620 109
map01bf@620 110 /*engage power thresholding in the referenced db*/
map01bf@620 111 /*api call:*/
map01bf@620 112 // int audiodb_power(adb_ptr mydb);
map01bf@620 113 PyObject * _pyadb_power(PyObject *self, PyObject *args)
map01bf@620 114 {
map01bf@620 115 adb_ptr current_db;
map01bf@620 116 int ok;
map01bf@620 117 PyObject * incoming = 0;
map01bf@620 118
map01bf@620 119 ok = PyArg_ParseTuple(args, "O", &incoming);
map01bf@620 120 if (!ok) return 0;
map01bf@620 121 current_db = (adb_ptr)PyCObject_AsVoidPtr(incoming);
map01bf@620 122
map01bf@620 123 ok = audiodb_power(current_db);
map01bf@622 124 return PyBool_FromLong(ok-1);
map01bf@620 125
map01bf@620 126 }
map01bf@621 127 /* insert feature data stored in a file */
map01bf@621 128 /* this is a bit gross, */
map01bf@621 129 /* should be replaced eventually by a numpy based feature.*/
map01bf@621 130 /* api call: */
map01bf@621 131 // struct adbinsert {
map01bf@621 132 // const char *features;
map01bf@621 133 // const char *power;
map01bf@621 134 // const char *key;
map01bf@621 135 // const char *times;
map01bf@621 136 // };
map01bf@621 137 // int audiodb_insert(adb_ptr mydb, adb_insert_ptr ins);
map01bf@621 138 PyObject * _pyadb_insertFromFile(PyObject *self, PyObject *args, PyObject *keywds)
map01bf@621 139 {
map01bf@621 140 adb_ptr current_db;
map01bf@621 141 adb_insert_ptr ins;
map01bf@621 142 int ok;
map01bf@621 143 const char *features;
map01bf@621 144 const char *power = NULL;
map01bf@621 145 const char *key = NULL;
map01bf@621 146 const char *times = NULL;
map01bf@621 147 PyObject * incoming = 0;
map01bf@621 148 static char *kwlist[] = { "db", "features", "power", "key", "times" , NULL};
map01bf@621 149
map01bf@621 150 ok = PyArg_ParseTupleAndKeywords(args, keywds, "Os|sss", kwlist, &incoming, &features, &power, &key, &times);
map01bf@621 151 if (!ok){return NULL;}
map01bf@621 152
map01bf@621 153 current_db = (adb_ptr)PyCObject_AsVoidPtr(incoming);
map01bf@621 154 ins = (adb_insert_ptr)malloc(sizeof(adb_insert_t));
map01bf@621 155 ins->features = features;
map01bf@621 156 ins->power = power;
map01bf@621 157 ins->key = key;
map01bf@621 158 ins->times = times;
map01bf@622 159 //printf("features::%s\npower::%s\nkey::%s\ntimes::%s\n", ins->features, ins->power, ins->key, ins->times);
map01bf@621 160 ok = audiodb_insert(current_db, ins);
map01bf@622 161 return PyBool_FromLong(ok-1);
map01bf@621 162
map01bf@621 163 }
map01bf@621 164
map01bf@622 165 /* base query. The nomenclature here is about a far away as pythonic as is possible.
map01bf@622 166 * This should be taken care of via the higher level python structure
map01bf@622 167 * returns a dict that should be result ordered and key = result key
map01bf@622 168 * and value is a list of tuples one per result associated with that key, of the form:
map01bf@622 169 * (dist, qpos, ipos)
map01bf@622 170 * Note as well that this is by no means the most efficient way to cast from C, simply the most direct
map01bf@622 171 * and what it lacks in effeciency it gains in python side access. It remains to be seen if this is
map01bf@622 172 * a sensible trade.
map01bf@622 173 * api call:
map01bf@622 174 * adb_query_results_t *audiodb_query_spec(adb_t *, const adb_query_spec_t *);
map01bf@622 175 ***/
map01bf@622 176 PyObject * _pyadb_queryFromKey(PyObject *self, PyObject *args, PyObject *keywds)
map01bf@622 177 {
map01bf@622 178 adb_ptr current_db;
map01bf@622 179 adb_query_spec_t *spec;
map01bf@622 180 adb_query_results_t *result;
map01bf@622 181 int ok, exhaustive, falsePositives;
map01bf@622 182 uint32_t i;
map01bf@622 183 const char *key;
map01bf@622 184 const char *accuMode = "db";
map01bf@622 185 const char *distMode = "dot";
map01bf@624 186 const char *resFmt = "dict";
map01bf@622 187 uint32_t hop = 0;
map01bf@622 188 double radius = 0;
map01bf@622 189 double absThres = 0;
map01bf@622 190 double relThres = 0;
map01bf@622 191 double durRatio = 0;
map01bf@622 192 PyObject *includeKeys = NULL;
map01bf@622 193 PyObject *excludeKeys = NULL;
map01bf@622 194 PyObject *incoming = 0;
map01bf@622 195 PyObject *outgoing = NULL;
map01bf@622 196 PyObject *thisKey = NULL;
map01bf@622 197 PyObject *currentValue = 0;
map01bf@622 198 PyObject *newBits = 0;
map01bf@622 199 static char *kwlist[] = { "db", "key",
map01bf@622 200 "seqLength",
map01bf@622 201 "seqStart",
map01bf@622 202 "exhaustive",
map01bf@622 203 "falsePositives",
map01bf@622 204 "accumulation",
map01bf@622 205 "distance",
map01bf@622 206 "npoints",//nearest neighbor points per track
map01bf@624 207 "ntracks",
map01bf@622 208 "includeKeys",
map01bf@622 209 "excludeKeys",
map01bf@622 210 "radius",
map01bf@622 211 "absThres",
map01bf@622 212 "relThres",
map01bf@622 213 "durRatio",
map01bf@624 214 "hopSize",
map01bf@624 215 "resFmt"
map01bf@622 216 };
map01bf@622 217 spec = (adb_query_spec_t *)malloc(sizeof(adb_query_spec_t));
map01bf@622 218 spec->qid.datum = (adb_datum_t *)malloc(sizeof(adb_datum_t));
map01bf@622 219 result = (adb_query_results_t *)malloc(sizeof(adb_query_results_t));
map01bf@622 220
map01bf@622 221 spec->qid.sequence_length = 16;
map01bf@622 222 spec->qid.sequence_start = 0;
map01bf@622 223 spec->qid.flags = 0;
map01bf@622 224 spec->params.npoints = 1;
map01bf@622 225 spec->params.ntracks = 100;//number of results returned in db mode
map01bf@622 226 spec->refine.flags = 0;
map01bf@622 227
map01bf@624 228 ok = PyArg_ParseTupleAndKeywords(args, keywds, "Os|iiiissIIOOddddIs", kwlist,
map01bf@622 229 &incoming, &key,
map01bf@622 230 &spec->qid.sequence_length,
map01bf@622 231 &spec->qid.sequence_start,
map01bf@622 232 &exhaustive, &falsePositives,
map01bf@622 233 &accuMode,&distMode,
map01bf@622 234 &spec->params.npoints,
map01bf@622 235 &spec->params.ntracks,
map01bf@622 236 &includeKeys, &excludeKeys,
map01bf@624 237 &radius, &absThres, &relThres, &durRatio, &hop,
map01bf@624 238 &resFmt
map01bf@622 239 );
map01bf@622 240
map01bf@622 241 if (!ok) {return NULL;}
map01bf@622 242 current_db = (adb_ptr)PyCObject_AsVoidPtr(incoming);
map01bf@622 243
map01bf@622 244 if (exhaustive){
map01bf@622 245 spec->qid.flags = spec->qid.flags | ADB_QID_FLAG_EXHAUSTIVE;
map01bf@622 246 }
map01bf@622 247 if (falsePositives){
map01bf@622 248 spec->qid.flags = spec->qid.flags | ADB_QID_FLAG_ALLOW_FALSE_POSITIVES;
map01bf@622 249 }
map01bf@622 250
map01bf@622 251 //set up spec->params
map01bf@622 252 if (strcmp(accuMode,"db")){
map01bf@622 253 spec->params.accumulation = ADB_ACCUMULATION_DB;
map01bf@622 254 } else if (strcmp(accuMode,"track")){
map01bf@622 255 spec->params.accumulation = ADB_ACCUMULATION_PER_TRACK;
map01bf@622 256 } else if (strcmp(accuMode,"one2one")){
map01bf@622 257 spec->params.accumulation = ADB_ACCUMULATION_ONE_TO_ONE;
map01bf@622 258 } else{
map01bf@624 259 PyErr_SetString(PyExc_ValueError,
map01bf@624 260 "Poorly specified distance mode. distance must either be \'db\', \'track\' or \'one2one\'.\n");
map01bf@622 261 return NULL;
map01bf@622 262 }
map01bf@622 263 if (strcmp(distMode, "dot")){
map01bf@622 264 spec->params.distance = ADB_DISTANCE_DOT_PRODUCT;
map01bf@622 265 }else if (strcmp(distMode, "eucNorm")){
map01bf@622 266 spec->params.distance = ADB_DISTANCE_EUCLIDEAN_NORMED;
map01bf@622 267 }else if (strcmp(distMode, "euclidean")){
map01bf@622 268 spec->params.distance = ADB_DISTANCE_EUCLIDEAN;
map01bf@622 269 }else{
map01bf@624 270 PyErr_SetString(PyExc_ValueError,
map01bf@624 271 "Poorly specified distance mode. distance must either be \'dot\', \'eucNorm\' or \'euclidean\'.\n");
map01bf@622 272 return NULL;
map01bf@622 273 }
map01bf@622 274
map01bf@622 275 //set up spec->refine
map01bf@622 276 //include/exclude keys
map01bf@622 277 if (includeKeys){
map01bf@622 278 if (!PyList_Check(includeKeys)){
map01bf@624 279 PyErr_SetString(PyExc_TypeError, "Include keys must be specified as a list of strings.\n");
map01bf@622 280 return NULL;
map01bf@622 281 }
map01bf@622 282 spec->refine.flags = spec->refine.flags | ADB_REFINE_INCLUDE_KEYLIST;
map01bf@622 283 spec->refine.include.nkeys = (uint32_t)PyList_Size(includeKeys);
map01bf@622 284 spec->refine.include.keys = (const char **)calloc(sizeof(const char *), spec->refine.include.nkeys);
map01bf@622 285 for (i=0;i<spec->refine.include.nkeys;i++){
map01bf@622 286 if (PyString_Check(PyList_GetItem(includeKeys, (Py_ssize_t)i))){
map01bf@622 287 spec->refine.include.keys[i] = PyString_AsString(PyList_GetItem(includeKeys, (Py_ssize_t)i));
map01bf@622 288 }else{
map01bf@624 289 PyErr_SetString(PyExc_TypeError, "Include keys must each be specified as a string.\nFound one that was not.\n");
map01bf@622 290 return NULL;
map01bf@622 291 }
map01bf@622 292 }
map01bf@622 293 }
map01bf@622 294 if (excludeKeys){
map01bf@622 295 if (!PyList_Check(excludeKeys)){
map01bf@624 296 PyErr_SetString(PyExc_TypeError, "Exclude keys must be specified as a list of strings.\n");
map01bf@622 297 return NULL;
map01bf@622 298 }
map01bf@622 299 spec->refine.flags = spec->refine.flags | ADB_REFINE_EXCLUDE_KEYLIST;
map01bf@622 300 spec->refine.exclude.nkeys = (uint32_t)PyList_Size(excludeKeys);
map01bf@622 301 spec->refine.exclude.keys = (const char **)calloc(sizeof(const char *), spec->refine.exclude.nkeys);
map01bf@622 302 for (i=0;i<spec->refine.exclude.nkeys;i++){
map01bf@622 303 if (PyString_Check(PyList_GetItem(excludeKeys, (Py_ssize_t)i))){
map01bf@622 304 spec->refine.exclude.keys[i] = PyString_AsString(PyList_GetItem(excludeKeys, (Py_ssize_t)i));
map01bf@622 305 }else{
map01bf@624 306 PyErr_SetString(PyExc_TypeError, "Exclude keys must each be specified as a string.\nFound one that was not.\n");
map01bf@622 307 return NULL;
map01bf@622 308 }
map01bf@622 309 }
map01bf@622 310 }
map01bf@622 311 //the rest of spec->refine
map01bf@622 312 if (radius){
map01bf@622 313 spec->refine.flags = spec->refine.flags | ADB_REFINE_RADIUS;
map01bf@622 314 spec->refine.radius = radius;
map01bf@622 315 }
map01bf@622 316 if (absThres){
map01bf@622 317 spec->refine.flags = spec->refine.flags | ADB_REFINE_ABSOLUTE_THRESHOLD;
map01bf@622 318 spec->refine.absolute_threshold = absThres;
map01bf@622 319 }
map01bf@622 320 if (relThres){
map01bf@622 321 spec->refine.flags = spec->refine.flags | ADB_REFINE_RELATIVE_THRESHOLD;
map01bf@622 322 spec->refine.relative_threshold = relThres;
map01bf@622 323 }
map01bf@622 324 if (durRatio){
map01bf@622 325 spec->refine.flags = spec->refine.flags | ADB_REFINE_DURATION_RATIO;
map01bf@622 326 spec->refine.duration_ratio = durRatio;
map01bf@622 327 }
map01bf@622 328 if (hop){
map01bf@622 329 spec->refine.flags = spec->refine.flags | ADB_REFINE_HOP_SIZE;
map01bf@622 330 spec->refine.hopsize = hop;
map01bf@622 331 }
map01bf@622 332 //setup the datum
map01bf@622 333 spec->qid.datum->data = NULL;
map01bf@622 334 spec->qid.datum->power = NULL;
map01bf@622 335 spec->qid.datum->times = NULL;
map01bf@622 336 //grab the datum from the key
map01bf@622 337 ok = audiodb_retrieve_datum(current_db, key, spec->qid.datum);
map01bf@622 338 if (ok != 0){
map01bf@622 339 PyErr_SetString(PyExc_RuntimeError, "Encountered an error while trying to retrieve the data associated with the passed key.\n");
map01bf@622 340 return NULL;
map01bf@622 341 }
map01bf@622 342 result = audiodb_query_spec(current_db, spec);
map01bf@622 343 if (result == NULL){
map01bf@622 344 PyErr_SetString(PyExc_RuntimeError, "Encountered an error while running the actual query.\n");
map01bf@622 345 return NULL;
map01bf@622 346 }
map01bf@624 347 if(strcmp(resFmt, "dict")==0){
map01bf@624 348 outgoing = PyDict_New();
map01bf@624 349 for (i=0;i<result->nresults;i++){
map01bf@624 350 thisKey = PyString_FromString(result->results[i].key);
map01bf@624 351 if (!PyDict_Contains(outgoing, thisKey)){
map01bf@624 352 newBits = Py_BuildValue("[(dII)]",
map01bf@624 353 result->results[i].dist,
map01bf@624 354 result->results[i].qpos,
map01bf@624 355 result->results[i].ipos);
map01bf@624 356 if (PyDict_SetItem(outgoing, thisKey,newBits)){
map01bf@624 357 printf("key : %s\ndist : %f\nqpos : %i\nipos : %i\n", result->results[i].key, result->results[i].dist, result->results[i].qpos, result->results[i].ipos);
map01bf@624 358 PyErr_SetString(PyExc_AttributeError, "Error adding a tuple to the result dict\n");
map01bf@624 359 Py_XDECREF(newBits);
map01bf@624 360 return NULL;
map01bf@624 361 }
map01bf@624 362 Py_DECREF(newBits);
map01bf@624 363 }else {
map01bf@624 364 //the key already has a value, so we need to fetch the value, confirm it's a list and append another tuple to it.
map01bf@624 365 currentValue = PyDict_GetItem(outgoing, thisKey);
map01bf@624 366 if (!PyList_Check(currentValue)){
map01bf@624 367 PyErr_SetString(PyExc_TypeError, "The result dictionary appears to be malformed.\n");
map01bf@624 368 return NULL;
map01bf@624 369 }
map01bf@624 370 newBits = Py_BuildValue("dII",result->results[i].dist,
map01bf@624 371 result->results[i].qpos,
map01bf@624 372 result->results[i].ipos);
map01bf@624 373 if (PyList_Append(currentValue, newBits)){
map01bf@624 374 //error msg here
map01bf@624 375 Py_XDECREF(newBits);
map01bf@624 376 return NULL;
map01bf@624 377 }
map01bf@624 378 if (PyDict_SetItem(outgoing, thisKey, newBits)){
map01bf@624 379 PyErr_SetString(PyExc_AttributeError, "Error adding a tuple to the result dict\n");
map01bf@624 380 Py_XDECREF(newBits);
map01bf@624 381 return NULL;
map01bf@624 382 }
map01bf@624 383 Py_DECREF(newBits);
map01bf@624 384
map01bf@624 385 }
map01bf@624 386 }
map01bf@624 387 }else if(strcmp(resFmt, "list")==0){
map01bf@624 388 outgoing = PyList_New((Py_ssize_t)0);
map01bf@624 389 for (i=0;i<result->nresults;i++){
map01bf@624 390 newBits = Py_BuildValue("sdII",result->results[i].key,
map01bf@622 391 result->results[i].dist,
map01bf@622 392 result->results[i].qpos,
map01bf@622 393 result->results[i].ipos);
map01bf@624 394 if (PyList_Append(outgoing, newBits)){
map01bf@624 395 //error msg here
map01bf@622 396 Py_XDECREF(newBits);
map01bf@622 397 return NULL;
map01bf@622 398 }
map01bf@622 399 Py_DECREF(newBits);
map01bf@624 400 }
map01bf@624 401 if(PyList_Reverse(outgoing)){//need to do this as things come off the accumulator backward.
map01bf@624 402 printf("the reverse failed, hopefully a sensable error will follow.\nIf not, fix it.\n");
map01bf@624 403 return NULL;
map01bf@622 404 }
map01bf@624 405 }else{
map01bf@624 406 PyErr_SetString(PyExc_ValueError,
map01bf@624 407 "Poorly specified result mode. Result must be either \'dist\' or \'list\'.\n");
map01bf@624 408 return NULL;
map01bf@622 409 }
map01bf@622 410 if (!audiodb_query_free_results(current_db, spec, result)){
map01bf@622 411 printf("bit of trouble freeing the result and spec...\ncheck for leaks.");
map01bf@622 412 }
map01bf@622 413
map01bf@622 414 return outgoing;
map01bf@622 415
map01bf@622 416
map01bf@622 417
map01bf@622 418 }
map01bf@622 419
map01bf@622 420
map01bf@622 421
map01bf@622 422
map01bf@620 423 /* close a database */
map01bf@620 424 /* api call: */
map01bf@620 425 // void audiodb_close(adb_ptr db);
map01bf@620 426 static void _pyadb_close(void *ptr)
map01bf@620 427 {
map01bf@620 428 adb_ptr stale_database;
map01bf@620 429 stale_database = (adb_ptr)ptr;
map01bf@620 430
map01bf@620 431 audiodb_close(stale_database);
map01bf@620 432 }
map01bf@620 433
map01bf@620 434 static PyMethodDef _pyadbMethods[] =
map01bf@620 435 {
map01bf@620 436 { "_pyadb_create", _pyadb_create, METH_VARARGS,
map01bf@620 437 "_pyadb_create(string path, unsigned datasize, unsigned ntracks, unsigned datadim)->adb object"},
map01bf@620 438 { "_pyadb_open", _pyadb_open, METH_VARARGS,
map01bf@620 439 "_pyadb_open(string path, [\'r\'|\'w\'])->adb object\nNote that specifing \'w\' opens the file in read and write mode. \
map01bf@620 440 There is currently no way to open in write only."},
map01bf@620 441 { "_pyadb_status", _pyadb_status, METH_VARARGS,
map01bf@620 442 "_status(adb_ptr)->(numFiles, dims, dudCount, nullCount, flags, length, data_region_size)"},
map01bf@620 443 { "_pyadb_l2norm", _pyadb_l2norm, METH_VARARGS,
map01bf@620 444 "_pyadb_l2norm(adb_ptr)->int return code (0 for sucess)"},
map01bf@620 445 { "_pyadb_power", _pyadb_power, METH_VARARGS,
map01bf@620 446 "_pyadb_power(adb_ptr)->int return code (0 for sucess)"},
map01bf@622 447 { "_pyadb_insertFromFile", (PyCFunction)_pyadb_insertFromFile, METH_VARARGS | METH_KEYWORDS,
map01bf@621 448 "_pyadb_insertFromFile(adb_ptr, features=featureFile, [power=powerfile | key=keystring | times=timingFile])->\
map01bf@621 449 int return code (0 for sucess)"},
map01bf@622 450 { "_pyadb_queryFromKey", (PyCFunction)_pyadb_queryFromKey, METH_VARARGS | METH_KEYWORDS,
map01bf@622 451 "base query. The nomenclature here is about a far away as pythonic as is possible.\n\
map01bf@622 452 This should be taken care of via the higher level python structure\n\
map01bf@622 453 returns a dict that should be result ordered and key = result key\n\
map01bf@622 454 and value is a list of tuples one per result associated with that key, of the form:\n\
map01bf@622 455 \t(dist, qpos, ipos)\n\
map01bf@622 456 Note as well that this is by no means the most efficient way to cast from C, simply the most direct\n\
map01bf@622 457 and what it lacks in effeciency it gains in python side access. It remains to be seen if this is\n\
map01bf@622 458 a sensible trade.\n\
map01bf@622 459 _pyadb_queryFromKey(adb_ptr, query key,\n\
map01bf@622 460 [seqLength = Int Sequence Length, \n\
map01bf@622 461 seqStart = Int offset from start for key, \n\
map01bf@622 462 exhaustive = boolean - True for exhaustive (false by default),\n\
map01bf@622 463 falsePositives= boolean - True to keep fps (false by defaults),\n\
map01bf@622 464 accumulation = [\"db\"|\"track\"|\"one2one\"] (\"db\" by default),\n\
map01bf@622 465 distance = [\"dot\"|\"eucNorm\"|\"euclidean\"] (\"dot\" by default),\n\
map01bf@622 466 npoints = int number of points per track,\n\
map01bf@622 467 ntracks = max number of results returned in db accu mode,\n\
map01bf@622 468 includeKeys = list of strings to include (use all by default),\n\
map01bf@622 469 excludeKeys = list of strings to exclude (none by default),\n\
map01bf@622 470 radius = double of nnRadius (1.0 default, overrides npoints if specified),\n\
map01bf@622 471 absThres = double absolute power threshold (db must have power),\n\
map01bf@622 472 relThres = double relative power threshold (db must have power),\n\
map01bf@622 473 durRatio = double time expansion/compresion ratio,\n\
map01bf@622 474 hopSize = int hopsize (1 by default)])->resultDict\n"},
map01bf@620 475 {NULL,NULL, 0, NULL}
map01bf@620 476 };
map01bf@620 477
map01bf@620 478 void init_pyadb()
map01bf@620 479 {
map01bf@620 480 Py_InitModule3("_pyadb", _pyadbMethods, "internal c bindings for audioDB. Use pyadb for pythonic access to adb (when it exists).");
map01bf@620 481 // import_array();
map01bf@620 482 return;
map01bf@620 483 }
map01bf@620 484
map01bf@620 485