Commit 763f3c96 authored by André Anjos's avatar André Anjos 💬

xbob.measure is now documented and with latest fixes

parent ab9c0ae9
.. vim: set fileencoding=utf-8 :
.. Andre Anjos <andre.dos.anjos@gmail.com>
.. Tue 15 Oct 14:59:05 2013
=========
C++ API
=========
The C++ API of ``xbob.io`` allows users to leverage from automatic converters
for classes in :py:class:`xbob.io`. To use the C API, clients should first,
include the header file ``<xbob.io/api.h>`` on their compilation units and
then, make sure to call once ``import_xbob_io()`` at their module
instantiation, as explained at the `Python manual
<http://docs.python.org/2/extending/extending.html#using-capsules>`_.
Here is a dummy C example showing how to include the header and where to call
the import function:
.. code-block:: c++
#include <xbob.io/api.h>
PyMODINIT_FUNC initclient(void) {
PyObject* m Py_InitModule("client", ClientMethods);
if (!m) return;
// imports the NumPy C-API
import_array();
// imports blitz.array C-API
import_blitz_array();
// imports xbob.core.random C-API
import_xbob_io();
}
.. note::
The include directory can be discovered using
:py:func:`xbob.io.get_include`.
Generic Functions
-----------------
.. cpp:function:: int PyBobIo_AsTypenum(bob::core::array::ElementType et)
Converts the input Bob element type into a ``NPY_<TYPE>`` enumeration value.
Returns ``NPY_NOTYPE`` in case of problems, and sets a
:py:class:`RuntimeError`.
.. cpp:function:: PyObject* PyBobIo_TypeInfoAsTuple (const bob::core::array::typeinfo& ti)
Converts the ``bob::core::array::typeinfo&`` object into a **new reference**
to a :py:class:`tuple` with 3 elements:
[0]
The data type as a :py:class:`numpy.dtype` object
[1]
The shape of the object, as a tuple of integers
[2]
The strides of the object, as a tuple of integers
Returns ``0`` in case of failure, or a **new reference** to the tuple
described above in case of success.
Bob File Support
----------------
.. cpp:type:: PyBobIoFileObject
The pythonic object representation for a ``bob::io::File`` object.
.. code-block:: cpp
typedef struct {
PyObject_HEAD
boost::shared_ptr<bob::io::File> f;
} PyBobIoFileObject;
.. cpp:member:: boost::shared_ptr<bob::io::File> f
A pointer to a file being read or written.
.. cpp:type:: PyBobIoFileIteratorObject
The pythonic object representation for an iterator over a ``bob::io::File``
object.
.. code-block:: cpp
typedef struct {
PyObject_HEAD
PyBobIoFileObject* pyfile;
Py_ssize_t curpos;
} PyBobIoFileIteratorObject;
.. cpp:member:: PyBobIoFileObject* pyfile
A pointer to the pythonic representation of a file.
.. cpp:member:: Py_ssize_t curpos
The current position at the file being pointed to.
Bob HDF5 Support
----------------
.. cpp:type:: PyBobIoHDF5FileObject
The pythonic object representation for a ``bob::io::HDF5File`` object.
.. code-block:: cpp
typedef struct {
PyObject_HEAD
boost::shared_ptr<bob::io::HDF5File> f;
} PyBobIoHDF5FileObject;
.. cpp:member:: boost::shared_ptr<bob::io::HDF5File> f
A pointer to a Bob object being used to read/write data into an HDF5
file.
.. cpp:function:: int PyBobIoHDF5File_Check(PyObject* o)
Checks if the input object ``o`` is a ``PyBobIoHDF5FileObject``. Returns
``1`` if it is, and ``0`` otherwise.
.. cpp:function:: int PyBobIoHDF5File_Converter(PyObject* o, PyBobIoHDF5FileObject** a)
This function is meant to be used with :c:func:`PyArg_ParseTupleAndKeywords`
family of functions in the Python C-API. It checks the input object to be of
type ``PyBobIoHDF5FileObject`` and sets a **new reference** to it (in
``*a``) if it is the case. Returns ``0`` in case of failure, ``1`` in case
of success.
Bob VideoReader Support
-----------------------
.. note::
The video C-API (and Python) is only available if the package was compiled
with FFMPEG or LibAV support.
.. cpp:type:: PyBobIoVideoReaderObject
The pythonic object representation for a ``bob::io::VideoReader`` object.
.. code-block:: cpp
typedef struct {
PyObject_HEAD
boost::shared_ptr<bob::io::VideoReader> v;
} PyBobIoVideoReaderObject;
.. cpp:member:: boost::shared_ptr<bob::io::VideoReader> v
A pointer to a Bob object being used to read the video contents
.. cpp:type:: PyBobIoVideoReaderIteratorObject
The pythonic object representation for an iterator over a
``bob::io::VideoReader`` object.
.. code-block:: cpp
typedef struct {
PyObject_HEAD
PyBobIoVideoReaderObject* pyreader;
boost::shared_ptr<bob::io::VideoReader::const_iterator> iter;
} PyBobIoFileIteratorObject;
.. cpp:member:: PyBobIoVideoReaderObject* pyreader
A pointer to the pythonic representation of the video reader.
.. cpp:member:: boost::shared_ptr<bob::io::VideoReader::const_iterator> iter
The current position at the file being pointed to, represented by a
formal iterator over the VideoReader.
.. cpp:type:: PyBobIoVideoReaderObject
The pythonic object representation for a ``bob::io::VideoWriter`` object.
.. code-block:: cpp
typedef struct {
PyObject_HEAD
boost::shared_ptr<bob::io::VideoWriter> v;
} PyBobIoVideoWriterObject;
.. cpp:member:: boost::shared_ptr<bob::io::VideoWriter> v
A pointer to a Bob object being used to write contents to the video.
.. include:: links.rst
This diff is collapsed.
.. vim: set fileencoding=utf-8 :
.. Andre Anjos <andre.anjos@idiap.ch>
.. Mon 4 Nov 20:58:04 2013 CET
..
..
.. Copyright (C) 2011-2013 Idiap Research Institute, Martigny, Switzerland
====================
......@@ -19,9 +19,7 @@ Reference
:maxdepth: 2
guide
video
py_api
c_cpp_api
Indices and tables
------------------
......
#!/usr/bin/env python
# vim: set fileencoding=utf-8 :
"""Tutorial for plotting a DET curve
"""
import bob
import numpy
from matplotlib import pyplot
positives = numpy.random.normal(1,1,100)
negatives = numpy.random.normal(-1,1,100)
npoints = 100
bob.measure.plot.det(negatives, positives, npoints, color=(0,0,0), linestyle='-', label='test')
bob.measure.plot.det_axis([0.1, 80, 0.1, 80])
pyplot.grid(True)
pyplot.xlabel('FAR (%)')
pyplot.ylabel('FRR (%)')
pyplot.title('DET')
#!/usr/bin/env python
# vim: set fileencoding=utf-8 :
"""Tutorial for plotting an EPC curve
"""
import bob
import numpy
from matplotlib import pyplot
dev_pos = numpy.random.normal(1,1,100)
dev_neg = numpy.random.normal(-1,1,100)
test_pos = numpy.random.normal(0.9,1,100)
test_neg = numpy.random.normal(-1.1,1,100)
npoints = 100
bob.measure.plot.epc(dev_neg, dev_pos, test_neg, test_pos, npoints, color=(0,0,0), linestyle='-')
pyplot.grid(True)
pyplot.title('EPC')
#!/usr/bin/env python
# vim: set fileencoding=utf-8 :
"""Tutorial for plotting a ROC curve
"""
import bob
import numpy
from matplotlib import pyplot
positives = numpy.random.normal(1,1,100)
negatives = numpy.random.normal(-1,1,100)
npoints = 100
bob.measure.plot.roc(negatives, positives, npoints, color=(0,0,0), linestyle='-', label='test')
pyplot.grid(True)
pyplot.xlabel('FAR (%)')
pyplot.ylabel('FRR (%)')
pyplot.title('ROC')
.. vim: set fileencoding=utf-8 :
.. Andre Anjos <andre.dos.anjos@gmail.com>
.. Sat 16 Nov 20:52:58 2013
.. Sat 16 Nov 20:52:58 2013
============
Python API
......@@ -9,37 +9,5 @@
This section includes information for using the pure Python API of ``xbob.io``.
Classes
-------
.. automodule:: xbob.io
.. autoclass:: xbob.io.File
.. autoclass:: xbob.io.HDF5File
.. autoclass:: xbob.io.VideoReader
.. autoclass:: xbob.io.VideoWriter
Functions
---------
.. autofunction:: xbob.io.load
.. autofunction:: xbob.io.merge
.. autofunction:: xbob.io.save
.. autofunction:: xbob.io.append
.. autofunction:: xbob.io.peek
.. autofunction:: xbob.io.peek_all
.. autofunction:: xbob.io.create_directories_save
C++ API Helpers
---------------
.. autofunction:: xbob.io.get_include
This diff is collapsed.
......@@ -53,9 +53,9 @@ static PyObject* epc(PyObject*, PyObject* args, PyObject* kwds) {
/* Parses input arguments in a single shot */
static const char* const_kwlist[] = {
"dev_negatives",
"dev_positives",
"test_positives",
"dev_negatives",
"dev_positives",
"test_positives",
"test_negatives",
"n_points",
0 /* Sentinel */
......@@ -124,8 +124,8 @@ static PyObject* det(PyObject*, PyObject* args, PyObject* kwds) {
/* Parses input arguments in a single shot */
static const char* const_kwlist[] = {
"negatives",
"positives",
"negatives",
"positives",
"n_points",
0 /* Sentinel */
};
......@@ -202,8 +202,8 @@ static PyObject* roc(PyObject*, PyObject* args, PyObject* kwds) {
/* Parses input arguments in a single shot */
static const char* const_kwlist[] = {
"negatives",
"positives",
"negatives",
"positives",
"n_points",
0 /* Sentinel */
};
......@@ -278,8 +278,8 @@ static PyObject* farfrr(PyObject*, PyObject* args, PyObject* kwds) {
/* Parses input arguments in a single shot */
static const char* const_kwlist[] = {
"negatives",
"positives",
"negatives",
"positives",
"threshold",
0 /* Sentinel */
};
......@@ -327,8 +327,8 @@ static PyObject* eer_threshold(PyObject*, PyObject* args, PyObject* kwds) {
/* Parses input arguments in a single shot */
static const char* const_kwlist[] = {
"negatives",
"positives",
"negatives",
"positives",
0 /* Sentinel */
};
static char** kwlist = const_cast<char**>(const_kwlist);
......@@ -372,8 +372,8 @@ static PyObject* min_weighted_error_rate_threshold(PyObject*, PyObject* args, Py
/* Parses input arguments in a single shot */
static const char* const_kwlist[] = {
"negatives",
"positives",
"negatives",
"positives",
"cost",
0 /* Sentinel */
};
......@@ -415,8 +415,8 @@ static PyObject* min_hter_threshold(PyObject*, PyObject* args, PyObject* kwds) {
/* Parses input arguments in a single shot */
static const char* const_kwlist[] = {
"negatives",
"positives",
"negatives",
"positives",
0 /* Sentinel */
};
static char** kwlist = const_cast<char**>(const_kwlist);
......@@ -460,8 +460,8 @@ static PyObject* precision_recall(PyObject*, PyObject* args, PyObject* kwds) {
/* Parses input arguments in a single shot */
static const char* const_kwlist[] = {
"negatives",
"positives",
"negatives",
"positives",
"threshold",
0 /* Sentinel */
};
......@@ -509,8 +509,8 @@ static PyObject* f_score(PyObject*, PyObject* args, PyObject* kwds) {
/* Parses input arguments in a single shot */
static const char* const_kwlist[] = {
"negatives",
"positives",
"negatives",
"positives",
"threshold",
"weight",
0 /* Sentinel */
......@@ -557,7 +557,7 @@ static PyObject* correctly_classified_negatives(PyObject*, PyObject* args, PyObj
/* Parses input arguments in a single shot */
static const char* const_kwlist[] = {
"negatives",
"negatives",
"threshold",
0 /* Sentinel */
};
......@@ -598,7 +598,7 @@ static PyObject* correctly_classified_positives(PyObject*, PyObject* args, PyObj
/* Parses input arguments in a single shot */
static const char* const_kwlist[] = {
"positives",
"positives",
"threshold",
0 /* Sentinel */
};
......@@ -640,8 +640,8 @@ static PyObject* precision_recall_curve(PyObject*, PyObject* args, PyObject* kwd
/* Parses input arguments in a single shot */
static const char* const_kwlist[] = {
"negatives",
"positives",
"negatives",
"positives",
"n_points",
0 /* Sentinel */
};
......@@ -696,8 +696,8 @@ static PyObject* far_threshold(PyObject*, PyObject* args, PyObject* kwds) {
/* Parses input arguments in a single shot */
static const char* const_kwlist[] = {
"negatives",
"positives",
"negatives",
"positives",
"threshold",
0 /* Sentinel */
};
......@@ -752,8 +752,8 @@ static PyObject* frr_threshold(PyObject*, PyObject* args, PyObject* kwds) {
/* Parses input arguments in a single shot */
static const char* const_kwlist[] = {
"negatives",
"positives",
"negatives",
"positives",
"frr_value",
0 /* Sentinel */
};
......@@ -796,8 +796,8 @@ static PyObject* eer_rocch(PyObject*, PyObject* args, PyObject* kwds) {
/* Parses input arguments in a single shot */
static const char* const_kwlist[] = {
"negatives",
"positives",
"negatives",
"positives",
0 /* Sentinel */
};
static char** kwlist = const_cast<char**>(const_kwlist);
......@@ -837,8 +837,8 @@ static PyObject* rocch(PyObject*, PyObject* args, PyObject* kwds) {
/* Parses input arguments in a single shot */
static const char* const_kwlist[] = {
"negatives",
"positives",
"negatives",
"positives",
0 /* Sentinel */
};
static char** kwlist = const_cast<char**>(const_kwlist);
......@@ -887,7 +887,7 @@ static PyObject* rocch2eer(PyObject*, PyObject* args, PyObject* kwds) {
/* Parses input arguments in a single shot */
static const char* const_kwlist[] = {
"pmiss_pfa",
"pmiss_pfa",
0 /* Sentinel */
};
static char** kwlist = const_cast<char**>(const_kwlist);
......@@ -921,8 +921,8 @@ static PyObject* roc_for_far(PyObject*, PyObject* args, PyObject* kwds) {
/* Parses input arguments in a single shot */
static const char* const_kwlist[] = {
"negatives",
"positives",
"negatives",
"positives",
"far_list",
0 /* Sentinel */
};
......@@ -1074,7 +1074,7 @@ static PyMethodDef library_methods[] = {
PyMODINIT_FUNC XBOB_EXT_ENTRY_NAME (void) {
PyObject* m = Py_InitModule3(XBOB_EXT_MODULE_NAME,
PyObject* m = Py_InitModule3(XBOB_EXT_MODULE_NAME,
library_methods, "bob::measure bindings");
PyModule_AddStringConstant(m, "__version__", XBOB_EXT_MODULE_VERSION);
......
......@@ -59,7 +59,7 @@ def roc(negatives, positives, npoints=100, CAR=False, **kwargs):
if not CAR:
return mpl.plot(100.0*out[0,:], 100.0*out[1,:], **kwargs)
else:
return mpl.semilogx(100.0*out[1,:], 100.0*(1-out[0,:]), **kwargs)
return mpl.semilogx(100.0*out[0,:], 100.0*(1-out[1,:]), **kwargs)
def precision_recall_curve(negatives, positives, npoints=100, **kwargs):
"""Plots Precision-Recall curve.
......
......@@ -102,8 +102,8 @@ def plots(dev_neg, dev_pos, test_neg, test_pos, npoints, filename):
linestyle='-', label='test')
mpl.axis([0,40,0,40])
mpl.title("ROC Curve")
mpl.xlabel('FRR (%)')
mpl.ylabel('FAR (%)')
mpl.xlabel('FAR (%)')
mpl.ylabel('FRR (%)')
mpl.grid(True, color=(0.3,0.3,0.3))
mpl.legend()
pp.savefig(fig)
......@@ -116,8 +116,8 @@ def plots(dev_neg, dev_pos, test_neg, test_pos, npoints, filename):
linestyle='-', label='test')
plot.det_axis([0.01, 40, 0.01, 40])
mpl.title("DET Curve")
mpl.xlabel('FRR (%)')
mpl.ylabel('FAR (%)')
mpl.xlabel('FAR (%)')
mpl.ylabel('FRR (%)')
mpl.grid(True, color=(0.3,0.3,0.3))
mpl.legend()
pp.savefig(fig)
......
......@@ -45,7 +45,7 @@ def test_basic_ratios():
prec, recall = precision_recall(negatives, positives, minimum-0.1)
nose.tools.eq_(prec, 0.5)
nose.tools.eq_(recall, 1.0)
# Similarly, if we take a threshold on the maximum, the FRR should be 1.0
# while the FAR should be 0.0. Both precision and recall should be 0.0.
far, frr = farfrr(negatives, positives, maximum+0.1)
......@@ -63,23 +63,23 @@ def test_basic_ratios():
prec, recall = precision_recall(negatives, positives, 3.0)
nose.tools.eq_(prec, 1.0)
nose.tools.eq_(recall, 1.0)
# Testing the values of F-score depending on different choices of the threshold
f_score_ = f_score(negatives, positives, minimum-0.1)
nose.tools.assert_almost_equal(f_score_, 0.66666667)
f_score_ = f_score(negatives, positives, minimum-0.1, 2)
nose.tools.assert_almost_equal(f_score_, 0.83333333)
f_score_ = f_score(negatives, positives, maximum+0.1)
nose.tools.eq_(f_score_, 0.0)
f_score_ = f_score(negatives, positives, maximum+0.1, 2)
nose.tools.eq_(f_score_, 0.0)
f_score_ = f_score(negatives, positives, 3.0)
nose.tools.eq_(f_score_, 1.0)
f_score_ = f_score(negatives, positives, 3.0, 2)
nose.tools.eq_(f_score_, 1.0)
def test_indexing():
......@@ -185,14 +185,14 @@ def test_plots():
# save('nonsep-roc.hdf5', xy)
xyref = xbob.io.load(F('nonsep-roc.hdf5'))
assert numpy.array_equal(xy, xyref)
# This example will test the Precision-Recall plot calculation functionality.
xy = precision_recall_curve(negatives, positives, 100)
# uncomment the next line to save a reference value
# save('nonsep-roc.hdf5', xy)
xyref = xbob.io.load(F('nonsep-precisionrecall.hdf5'))
assert numpy.array_equal(xy, xyref)
# This example will test the DET plot calculation functionality.
det_xyzw = det(negatives, positives, 100)
# uncomment the next line to save a reference value
......@@ -227,7 +227,7 @@ def test_rocch():
positives = xbob.io.load(F('linsep-positives.hdf5'))
negatives = xbob.io.load(F('linsep-negatives.hdf5'))
# References obtained using Bosaris 1.06
pmiss_pfa_ref = numpy.array([[0., 0, 1], [1, 0, 0]])
pmiss_pfa_ref = numpy.array([[1., 0., 0.], [0., 0., 1.]])
eer_ref = 0.
# Computes
pmiss_pfa = rocch(negatives, positives)
......@@ -241,7 +241,7 @@ def test_rocch():
positives = xbob.io.load(F('nonsep-positives.hdf5'))
negatives = xbob.io.load(F('nonsep-negatives.hdf5'))
# References obtained using Bosaris 1.06
pmiss_pfa_ref = numpy.array([[0, 0, 0.08, 0.12, 0.22, 0.48, 1.], [1., 0.68, 0.28, 0.1, 0.06, 0., 0.]])
pmiss_pfa_ref = numpy.array([[1., 0.68, 0.28, 0.1, 0.06, 0., 0.], [0, 0, 0.08, 0.12, 0.22, 0.48, 1.]])
eer_ref = 0.116363636363636
# Computes
pmiss_pfa = rocch(negatives, positives)
......@@ -250,7 +250,7 @@ def test_rocch():
assert abs(eer-eer_ref) < 1e-4
eer = eer_rocch(negatives, positives)
assert abs(eer-eer_ref) < 1e-4
def test_cmc():
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment