comparison bindings/python/pyadbmodule.c @ 746:91719fa0d45b

Added _pyadb_retrieveDatum for getting data, powers, or times as a numpy ndarray
author mas01mc
date Sat, 20 Nov 2010 15:26:41 +0000
parents 124ae047b968
children fbf16508421f
comparison
equal deleted inserted replaced
745:6dfde1f7a7eb 746:91719fa0d45b
13 #include "Python.h" 13 #include "Python.h"
14 #include "structmember.h" 14 #include "structmember.h"
15 #include "audioDB_API.h" 15 #include "audioDB_API.h"
16 #include "numpy/arrayobject.h" 16 #include "numpy/arrayobject.h"
17 17
18 #define ADB_HEADER_FLAG_L2NORM (0x1U)
19 #define ADB_HEADER_FLAG_POWER (0x4U)
20 #define ADB_HEADER_FLAG_TIMES (0x20U)
21 #define ADB_HEADER_FLAG_REFERENCES (0x40U)
22
18 static void _pyadb_close(void *ptr); 23 static void _pyadb_close(void *ptr);
19
20 24
21 /* create a new database */ 25 /* create a new database */
22 /* returns a struct or NULL on failure */ 26 /* returns a struct or NULL on failure */
23 /* api call: */ 27 /* api call: */
24 /* adb_t *audiodb_create(const char *path, unsigned datasize, unsigned ntracks, unsigned datadim);*/ 28 /* adb_t *audiodb_create(const char *path, unsigned datasize, unsigned ntracks, unsigned datadim);*/
31 ok = PyArg_ParseTuple(args, "sIII", &path, &datasize, &ntracks, &datadim); 35 ok = PyArg_ParseTuple(args, "sIII", &path, &datasize, &ntracks, &datadim);
32 if (!ok) return 0; 36 if (!ok) return 0;
33 new_database = audiodb_create(path, datasize, ntracks, datadim); 37 new_database = audiodb_create(path, datasize, ntracks, datadim);
34 if (!new_database) return 0; 38 if (!new_database) return 0;
35 39
36 return PyCObject_FromVoidPtr( new_database, _pyadb_close); 40 return PyCObject_FromVoidPtr( new_database, _pyadb_close);
37 } 41 }
38 42
39 /* open an existing database */ 43 /* open an existing database */
40 /* returns a struct or NULL on failure */ 44 /* returns a struct or NULL on failure */
41 /* flags expects fcntl flags concerning the opening mode */ 45 /* flags expects fcntl flags concerning the opening mode */
573 577
574 578
575 } 579 }
576 580
577 581
582 /* retrieval of inserted data
583 * returned numpy array has ndarray.shape = (numVectors, numDims)
584 * array datatype needs to be doubles (float may work...)
585 * if power reqeusted, it will be a 1d array of length numVectors
586 * if times are requested, they will be a 1d array of length 2*nvectors
587 */
588
589 // api call:
590 // typedef struct adb_datum {
591 // uint32_t nvectors;
592 // uint32_t dim;
593 // const char *key;
594 // double *data;
595 // double *power;
596 // double *times;
597 // } adb_datum_t;
598
599 //int audiodb_retrieve_datum(adb_t *, const char *, adb_datum_t *);
600 //int audiodb_free_datum(adb_t *, adb_datum_t *);
601 PyObject * _pyadb_retrieveDatum(PyObject *self, PyObject *args, PyObject *keywds)
602 {
603 adb_t *current_db = NULL;
604 adb_status_t *status = NULL;
605 adb_datum_t *ins = NULL;
606 int ok=0, errtest=0;
607 unsigned features=0, powers=0, times=0;
608 PyObject *incoming = 0; // The ADB database
609 PyObject *outgoing = 0; // The PyArrayObject
610 const char *key = NULL;
611 static char *kwlist[] = { "db", "key", "features", "powers", "times", NULL};
612 double * data;
613 int dims = 0;
614 npy_intp shape[2] = { 0, 0 };
615
616 ok = PyArg_ParseTupleAndKeywords(args, keywds, "Os|III", kwlist, &incoming, &key, &features, &powers, &times);
617 if (!ok){
618 PyErr_SetString(PyExc_TypeError, "Failed at PyArg_ParseTupleAndKeywords");
619 return NULL;
620 }
621
622 if(features+powers+times>1){
623 PyErr_SetString(PyExc_TypeError, "Failed: you must specify only one of features, powers, or times");
624 return NULL;
625 }
626
627 if(!(features||powers||times)){
628 features=1; // default is to return features
629 }
630
631 current_db = (adb_t *)PyCObject_AsVoidPtr(incoming);
632 if (!current_db){
633 PyErr_SetString(PyExc_TypeError, "Failed to convert open database to C-pointer");
634 return NULL;
635 }
636 status = (adb_status_t*) malloc(sizeof(adb_status_t));
637 errtest = audiodb_status(current_db, status);
638 if(errtest){
639 PyErr_SetString(PyExc_TypeError, "Failed: could not get status of passed ADB database");
640 free(status);
641 return NULL;
642 }
643
644 if(powers && !(status->flags&ADB_HEADER_FLAG_POWER)){
645 PyErr_SetString(PyExc_TypeError, "Failed: powers requested but passed ADB database has no powers");
646 free(status);
647 return NULL;
648 }
649
650 if(times && !(status->flags&ADB_HEADER_FLAG_TIMES)){
651 PyErr_SetString(PyExc_TypeError, "Failed: times requested but passed ADB database has no times");
652 free(status);
653 return NULL;
654 }
655
656 ins = (adb_datum_t *)malloc(sizeof(adb_datum_t));
657 errtest = audiodb_retrieve_datum(current_db, key, ins); // retrieve data from adb via key
658 if (errtest){
659 PyErr_SetString(PyExc_TypeError, "Failed to retrieve datum");
660 free(ins);
661 return NULL;
662 }
663
664 if(features){
665 if(ins->dim>1){
666 dims=2;
667 shape[1]= ins->dim;
668 }
669 else{
670 dims=1;
671 }
672 shape[0]= ins->nvectors;
673 data = ins->data;
674 }
675 else if(powers){
676 dims=1;
677 shape[0]= ins->nvectors;
678 data = ins->power;
679 }
680 else if(times){
681 dims=1;
682 shape[0]= 2 * ins->nvectors;
683 data = ins->times;
684 }
685
686 outgoing = PyArray_SimpleNewFromData(dims, shape, NPY_DOUBLE, data);
687 if (!outgoing){
688 PyErr_SetString(PyExc_TypeError, "Failed to convert retrieved datum to C-Array");
689 return NULL;
690 }
691 // Apprently Python automatically INCREFs the data pointer, so we don't have to call
692 // audiodb_free_datum(current_db, ins);
693 free(status);
694 free(ins); // free the malloced adb_datum_t structure though
695 return outgoing;
696 }
578 697
579 698
580 /* close a database */ 699 /* close a database */
581 /* api call: */ 700 /* api call: */
582 // void audiodb_close(adb_t *db); 701 // void audiodb_close(adb_t *db);
608 array given should have ndarray.shape = (numDims*numVectors,)\n\ 727 array given should have ndarray.shape = (numDims*numVectors,)\n\
609 array datatype needs to be doubles (float may work...)\n\ 728 array datatype needs to be doubles (float may work...)\n\
610 if power is given, must be 1d array of length numVectors\n\ 729 if power is given, must be 1d array of length numVectors\n\
611 if times is given, must be 1d array of length 2*numVectors like this:\n\ 730 if times is given, must be 1d array of length 2*numVectors like this:\n\
612 int audiodb_insert_datum(adb_t *, const adb_datum_t *);"}, 731 int audiodb_insert_datum(adb_t *, const adb_datum_t *);"},
732 {"_pyadb_retrieveDatum", (PyCFunction)_pyadb_retrieveDatum, METH_VARARGS | METH_KEYWORDS, "_pyadb_retrieveDatum(adb_t *, key=keystring"},
613 { "_pyadb_insertFromFile", (PyCFunction)_pyadb_insertFromFile, METH_VARARGS | METH_KEYWORDS, 733 { "_pyadb_insertFromFile", (PyCFunction)_pyadb_insertFromFile, METH_VARARGS | METH_KEYWORDS,
614 "_pyadb_insertFromFile(adb_t *, features=featureFile, [power=powerfile | key=keystring | times=timingFile])->\ 734 "_pyadb_insertFromFile(adb_t *, features=featureFile, [power=powerfile | key=keystring | times=timingFile])->\
615 int return code (0 for sucess)"}, 735 int return code (0 for sucess)"},
616 { "_pyadb_liszt", (PyCFunction)_pyadb_liszt, METH_VARARGS, 736 { "_pyadb_liszt", (PyCFunction)_pyadb_liszt, METH_VARARGS,
617 "_pyadb_liszt(adb_t*)->[[key1,numvecs1],[key2,numvecs2]...]"}, 737 "_pyadb_liszt(adb_t*)->[[key1,numvecs1],[key2,numvecs2]...]"},