pavx.cpp 5.71 KB
Newer Older
1
2
3
4
5
6
7
8
/**
 * @file math/python/pavx.cc
 * @date Sat Dec 8 20:53:50 2012 +0200
 * @author Laurent El Shafey <Laurent.El-Shafey@idiap.ch>
 *
 * @brief Binds the Pool-Adjacent-Violators Algorithm
 */

André Anjos's avatar
André Anjos committed
9
#include "pavx.h"
10
#include <bob.math/pavx.h>
11

André Anjos's avatar
André Anjos committed
12
13
#include <bob.blitz/cppapi.h>
#include <bob.blitz/cleanup.h>
André Anjos's avatar
André Anjos committed
14
#include <bob.core/cast.h>
15

André Anjos's avatar
André Anjos committed
16
PyObject* py_pavx (PyObject*, PyObject* args, PyObject* kwds) {
17

André Anjos's avatar
André Anjos committed
18
19
20
  /* Parses input arguments in a single shot */
  static const char* const_kwlist[] = { "input", "output", 0 /* Sentinel */ };
  static char** kwlist = const_cast<char**>(const_kwlist);
21

André Anjos's avatar
André Anjos committed
22
23
  PyBlitzArrayObject* input = 0;
  PyBlitzArrayObject* output = 0;
24

André Anjos's avatar
André Anjos committed
25
  if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&|O&",
26
27
        kwlist,
        &PyBlitzArray_Converter, &input,
André Anjos's avatar
André Anjos committed
28
29
        &PyBlitzArray_OutputConverter, &output
        )) return 0;
30

31
32
33
34
  //protects acquired resources through this scope
  auto input_ = make_safe(input);
  auto output_ = make_xsafe(output);

André Anjos's avatar
André Anjos committed
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
  // can only handle 1D arrays
  if (input->ndim != 1 || (output && output->ndim != 1)) {
    PyErr_SetString(PyExc_TypeError, "input and output arrays should be one-dimensional");
    return 0;
  }

  // can only handle float arrays
  if (input->type_num != NPY_FLOAT64 || (output && output->type_num != NPY_FLOAT64)) {
    PyErr_SetString(PyExc_TypeError, "input and output arrays data types should be float (i.e. `numpy.float64' equivalents)");
    return 0;
  }

  // if output was not provided by user
  bool returns_output = false;
  if (!output) {
    output = (PyBlitzArrayObject*)PyBlitzArray_SimpleNew(NPY_FLOAT64, input->ndim, input->shape);
51
    if (!output) return 0;
André Anjos's avatar
André Anjos committed
52
    returns_output = true;
53
    output_ = make_safe(output);
André Anjos's avatar
André Anjos committed
54
55
56
57
58
59
60
61
62
63
64
65
66
  }

  try {
    bob::math::pavx(*PyBlitzArrayCxx_AsBlitz<double,1>(input),
        *PyBlitzArrayCxx_AsBlitz<double,1>(output));
  }
  catch (std::exception& e) {
    PyErr_SetString(PyExc_RuntimeError, e.what());
  }
  catch (...) {
    PyErr_SetString(PyExc_RuntimeError, "pavx failed: unknown exception caught");
  }

67
  if (returns_output) {
68
    return PyBlitzArray_NUMPY_WRAP(Py_BuildValue("O", output));
69
70
  }

André Anjos's avatar
André Anjos committed
71
  Py_RETURN_NONE;
72
73
74

}

André Anjos's avatar
André Anjos committed
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
PyObject* py_pavx_width (PyObject*, PyObject* args, PyObject* kwds) {

  /* Parses input arguments in a single shot */
  static const char* const_kwlist[] = { "input", "output", 0 /* Sentinel */ };
  static char** kwlist = const_cast<char**>(const_kwlist);

  PyBlitzArrayObject* input = 0;
  PyBlitzArrayObject* output = 0;

  if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&O&",
        kwlist,
        &PyBlitzArray_Converter, &input,
        &PyBlitzArray_OutputConverter, &output
        )) return 0;

90
91
92
93
  //protects acquired resources through this scope
  auto input_ = make_safe(input);
  auto output_ = make_safe(output);

André Anjos's avatar
André Anjos committed
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
  // can only handle 1D arrays
  if (input->ndim != 1 || output->ndim != 1) {
    PyErr_SetString(PyExc_TypeError, "input and output arrays should be one-dimensional");
    return 0;
  }

  // can only handle float arrays
  if (input->type_num != NPY_FLOAT64 || output->type_num != NPY_FLOAT64) {
    PyErr_SetString(PyExc_TypeError, "input and output arrays data types should be float (i.e. `numpy.float64' equivalents)");
    return 0;
  }

  PyObject* retval = 0;

  try {
    blitz::Array<size_t,1> width =
      bob::math::pavxWidth(*PyBlitzArrayCxx_AsBlitz<double,1>(input),
          *PyBlitzArrayCxx_AsBlitz<double,1>(output));
    blitz::Array<uint64_t,1> uwidth = bob::core::array::cast<uint64_t>(width);
    retval = PyBlitzArrayCxx_NewFromArray(uwidth);
  }
  catch (std::exception& e) {
    PyErr_SetString(PyExc_RuntimeError, e.what());
117
    return 0;
André Anjos's avatar
André Anjos committed
118
119
120
  }
  catch (...) {
    PyErr_SetString(PyExc_RuntimeError, "pavx failed: unknown exception caught");
121
    return 0;
André Anjos's avatar
André Anjos committed
122
123
124
  }

  return retval;
125

126
127
}

André Anjos's avatar
André Anjos committed
128
129
130
131
132
133
134
135
136
137
PyObject* py_pavx_width_height (PyObject*, PyObject* args, PyObject* kwds) {

  /* Parses input arguments in a single shot */
  static const char* const_kwlist[] = { "input", "output", 0 /* Sentinel */ };
  static char** kwlist = const_cast<char**>(const_kwlist);

  PyBlitzArrayObject* input = 0;
  PyBlitzArrayObject* output = 0;

  if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&O&",
138
139
        kwlist,
        &PyBlitzArray_Converter, &input,
André Anjos's avatar
André Anjos committed
140
141
142
        &PyBlitzArray_OutputConverter, &output
        )) return 0;

143
144
145
146
  //protects acquired resources through this scope
  auto input_ = make_safe(input);
  auto output_ = make_safe(output);

André Anjos's avatar
André Anjos committed
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
  // can only handle 1D arrays
  if (input->ndim != 1 || output->ndim != 1) {
    PyErr_SetString(PyExc_TypeError, "input and output arrays should be one-dimensional");
    return 0;
  }

  // can only handle float arrays
  if (input->type_num != NPY_FLOAT64 || output->type_num != NPY_FLOAT64) {
    PyErr_SetString(PyExc_TypeError, "input and output arrays data types should be float (i.e. `numpy.float64' equivalents)");
    return 0;
  }

  PyObject* width = 0;
  PyObject* height = 0;

162
163
164
165
  //protects acquired resources through this scope
  auto width_ = make_xsafe(width);
  auto height_ = make_xsafe(height);

André Anjos's avatar
André Anjos committed
166
167
168
169
170
171
  try {
    std::pair<blitz::Array<size_t,1>,blitz::Array<double,1>> width_height =
      bob::math::pavxWidthHeight(*PyBlitzArrayCxx_AsBlitz<double,1>(input),
          *PyBlitzArrayCxx_AsBlitz<double,1>(output));
    blitz::Array<uint64_t,1> uwidth = bob::core::array::cast<uint64_t>(width_height.first);
    width = PyBlitzArrayCxx_NewFromArray(uwidth);
172
173
174
175
176
    if (!width) return 0;
    width_ = make_safe(width);
    height = PyBlitzArrayCxx_NewFromArray(width_height.second);
    if (!height) return 0;
    height_ = make_safe(height);
André Anjos's avatar
André Anjos committed
177
178
179
  }
  catch (std::exception& e) {
    PyErr_SetString(PyExc_RuntimeError, e.what());
180
    return 0;
André Anjos's avatar
André Anjos committed
181
182
183
  }
  catch (...) {
    PyErr_SetString(PyExc_RuntimeError, "pavx failed: unknown exception caught");
184
    return 0;
André Anjos's avatar
André Anjos committed
185
186
187
188
  }

  if (!height) return 0;

189
  return Py_BuildValue("OO", width, height);
André Anjos's avatar
André Anjos committed
190
}