OpenGM  2.3.x
Discrete Graphical Model Library
converter.hxx
Go to the documentation of this file.
1 #ifndef CONVERTER_IMPL_HXX
2 #define CONVERTER_IMPL_HXX
3 
4 #include <boost/python/detail/wrap_python.hpp>
5 #include <boost/python.hpp>
6 
7 #include <sstream>
8 //#include <Python.h>
9 #include <numpy/arrayobject.h>
10 
11 #include <boost/python/suite/indexing/vector_indexing_suite.hpp>
12 
13 
14 
15 #include <stdexcept>
16 #include <stddef.h>
17 #include <boost/python.hpp>
18 #include <boost/python/suite/indexing/vector_indexing_suite.hpp>
21 
22 namespace opengm{
23 namespace python{
24 
25 using namespace boost::python;
26 
27 
28 
29  template <typename T>
30  inline NPY_TYPES typeEnumFromType(void) {
31  PyErr_SetString(PyExc_ValueError, "no mapping available for this type");
32  boost::python::throw_error_already_set();
33  return NPY_VOID;
34  }
35 
36  //NPY_BOOL
37  template <> inline NPY_TYPES typeEnumFromType<bool>(void) {
38  return NPY_BOOL;
39  }
40 
41 
42  template <> inline NPY_TYPES typeEnumFromType<opengm::UInt8Type>(void) {
43  return NPY_UINT8;
44  }
45 
46  template <> inline NPY_TYPES typeEnumFromType<opengm::UInt16Type>(void) {
47  return NPY_UINT16;
48  }
49 
50  template <> inline NPY_TYPES typeEnumFromType<opengm::UInt32Type>(void) {
51  return NPY_UINT32;
52  }
53 
54  template <> inline NPY_TYPES typeEnumFromType<opengm::UInt64Type>(void) {
55  return NPY_UINT64;
56  }
57 
58  template <> inline NPY_TYPES typeEnumFromType<opengm::Int8Type>(void) {
59  return NPY_INT8;
60  }
61 
62  template <> inline NPY_TYPES typeEnumFromType<opengm::Int16Type>(void) {
63  return NPY_INT16;
64  }
65 
66  template <> inline NPY_TYPES typeEnumFromType<opengm::Int32Type>(void) {
67  return NPY_INT32;
68  }
69 
70  template <> inline NPY_TYPES typeEnumFromType<opengm::Int64Type>(void) {
71  return NPY_INT64;
72  }
73 
74  template <> inline NPY_TYPES typeEnumFromType<float>(void) {
75  return NPY_FLOAT32;
76  }
77 
78  template <> inline NPY_TYPES typeEnumFromType<double>(void) {
79  return NPY_FLOAT64;
80  }
81 
82 
83 
84 
85 template<class VALUE_TYPE>
86 inline boost::python::object get1dArray(const size_t size){
87  npy_intp dims[1]={static_cast<int>(size)};
88  boost::python::object obj(boost::python::handle<>(PyArray_SimpleNew(int(1), dims, typeEnumFromType<VALUE_TYPE>() )));
89  return obj;
90 }
91 
92 template<class VALUE_TYPE>
93 inline boost::python::object get2dArray(const size_t size1,const size_t size2){
94  npy_intp dims[2]={static_cast<int>(size1),static_cast<int>(size2)};
95  boost::python::object obj(boost::python::handle<>(PyArray_SimpleNew(int(2), dims, typeEnumFromType<VALUE_TYPE>() )));
96  return obj;
97 }
98 
99 
100 template<class VALUE_TYPE,class FORWARD_SHAPE_ITERATOR>
101 inline boost::python::object getArray(FORWARD_SHAPE_ITERATOR begin,FORWARD_SHAPE_ITERATOR end){
102  const int nDim=std::distance(begin,end);
103  npy_intp * dims = new npy_intp[nDim];
104  std::copy(begin,end,dims);
105  boost::python::object obj(boost::python::handle<>(PyArray_SimpleNew(nDim, dims, typeEnumFromType<VALUE_TYPE>() )));
106  delete[] dims;
107  return obj;
108 }
109 
110 template<class VALUE_TYPE>
111 inline VALUE_TYPE * getCastedPtr(boost::python::object obj){
112  void *array_data = PyArray_DATA((PyArrayObject*) obj.ptr());
113  return static_cast< VALUE_TYPE *>(array_data);
114 }
115 
116 inline boost::python::numeric::array objToArray(boost::python::object obj){
117  return boost::python::extract<boost::python::numeric::array > (obj);
118 }
119 
120 
121 
122 
123 inline std::string printEnum(PyArray_TYPES value) {
124  if (value == PyArray_UBYTE) return std::string("PyArray_UBYTE");
125  else if (value == PyArray_BOOL) return std::string("PyArray_BOOL");
126  else if (value == PyArray_UINT8) return std::string("PyArray_UINT8");
127  else if (value == PyArray_UINT16) return std::string("PyArray_UINT16");
128  else if (value == PyArray_UINT32) return std::string("PyArray_UINT32");
129  else if (value == PyArray_UINT64) return std::string("PyArray_UINT64");
130  else if (value == PyArray_INT8) return std::string("PyArray_INT8");
131  else if (value == PyArray_INT16) return std::string("PyArray_INT16");
132  else if (value == PyArray_INT32) return std::string("PyArray_INT32");
133  else if (value == PyArray_INT64) return std::string("PyArray_INT64");
134  else if (value == PyArray_FLOAT32) return std::string("PyArray_FLOAT32");
135  else if (value == PyArray_FLOAT64) return std::string("PyArray_FLOAT64");
136  else if (value == PyArray_BYTE) return std::string("PyArray_BYTE");
137  else if (value == PyArray_UBYTE) return std::string("PyArray_UBYTE");
138  else if (value == PyArray_USHORT) return std::string("PyArray_USHORT");
139  else if (value == PyArray_INT) return std::string("PyArray_INT");
140  else if (value == PyArray_UINT) return std::string("PyArray_UINT");
141  else if (value == PyArray_LONG) return std::string("PyArray_LONG");
142  else if (value == PyArray_ULONG) return std::string("PyArray_ULONG");
143  else if (value == PyArray_LONGLONG) return std::string("PyArray_LONGLONG");
144  else if (value == PyArray_DOUBLE) return std::string("PyArray_DOUBLE");
145  else if (value == PyArray_LONGDOUBLE) return std::string("PyArray_LONGDOUBLE");
146  else if (value == PyArray_FLOAT) return std::string("PyArray_FLOAT");
147  else if (value == PyArray_CFLOAT) return std::string("PyArray_CFLOAT");
148  else if (value == PyArray_CDOUBLE) return std::string("PyArray_CDOUBLE");
149 
150  else return " unkown type";
151 }
152 
153 template<class ITERATOR>
154 inline boost::python::tuple iteratorToTuple(ITERATOR iter, size_t size) {
155  typedef typename std::iterator_traits<ITERATOR>::value_type ValueType;
156  PyObject* tuple = PyTuple_New(size);
157  if (opengm::meta::Compare<ValueType, opengm::UInt8Type>::value ||
158  opengm::meta::Compare<ValueType, opengm::UInt16Type>::value ||
159  opengm::meta::Compare<ValueType, opengm::UInt32Type>::value ||
160  opengm::meta::Compare<ValueType, opengm::Int8Type>::value ||
161  opengm::meta::Compare<ValueType, opengm::Int16Type>::value ||
162  opengm::meta::Compare<ValueType, opengm::Int32Type>::value
163  ) {
164  for (size_t i = 0; i<size; ++i) {
165  PyTuple_SetItem(tuple, i, PyInt_FromLong(long(iter[i])));
166  }
167  }
168  else if (opengm::meta::Compare<ValueType, opengm::UInt64Type>::value ||
169  opengm::meta::Compare<ValueType, opengm::Int64Type>::value
170  ) {
171  for (size_t i = 0; i<size; ++i) {
172  PyTuple_SetItem(tuple, i, PyLong_FromLong(long(iter[i])));
173  }
174  }
175  else if (opengm::meta::Compare<ValueType, opengm::Float32Type>::value ||
176  opengm::meta::Compare<ValueType, opengm::Float64Type>::value) {
177  for (size_t i = 0; i<size; ++i) {
178  PyTuple_SetItem(tuple, i, PyFloat_FromDouble(double(iter[i])));
179  }
180  }
181  else {
182  opengm::RuntimeError("selected type is not supported in this to-tuple converter ");
183  }
184  boost::python::tuple t = boost::python::extract<boost::python::tuple > (tuple);
185  return t;
186 }
187 
188 template<class ITERATOR>
189 inline boost::python::list iteratorToList(ITERATOR iter, size_t size) {
190  typedef typename std::iterator_traits<ITERATOR>::value_type ValueType;
191  boost::python::list l;
192  for(size_t i=0;i<size;++i)
193  l.append(iter[i]);
194  return l;
195 }
196 
197 template<class ITERATOR>
198 inline boost::python::numeric::array iteratorToNumpy(ITERATOR iter, size_t size) {
199  typedef typename std::iterator_traits<ITERATOR>::value_type ValueType;
200  boost::python::object obj = get1dArray<ValueType>(size);
201  ValueType * castedPtr = getCastedPtr<ValueType>(obj);
202  for(size_t i=0;i<size;++i)
203  castedPtr[i]=iter[i];
204  return objToArray(obj);
205 }
206 
207 template<class NUMERIC_ARRAY>
208 inline PyArray_TYPES getArrayType(NUMERIC_ARRAY arr) {
209  return PyArray_TYPES(PyArray_TYPE(arr.ptr()));
210 }
211 
212 inline boost::python::numeric::array extractConstNumericArray
213 (
214  PyObject * obj
215 ) {
216  return boost::python::extract<boost::python::numeric::array > (obj);
217 }
218 
219 inline int numpyScalarTypeNumber(PyObject* obj) {
220  PyArray_Descr* dtype;
221  if (!PyArray_DescrConverter(obj, &dtype)) return NPY_NOTYPE;
222  int typeNum = dtype->type_num;
223  Py_DECREF(dtype);
224  return typeNum;
225 }
226 
227 template<class VALUE_TYPE,size_t DIM>
229  typedef VALUE_TYPE ValueType;
231 
233  boost::python::converter::registry::push_back(&convertible, &construct, boost::python::type_id<NumpyViewType > ());
234  }
235 
236  // Determine if obj_ptr can be converted in a NumpyViewType
237 
238  static void* convertible(PyObject * obj_ptr) {
239  if (!PyArray_Check(obj_ptr)) {
240  //PyErr_SetString(PyExc_ValueError, "expected a PyArrayObject");
241  return 0;
242  } else {
243  numeric::array numpyArray = extractConstNumericArray(obj_ptr);
244  PyArray_TYPES pyArrayType = getArrayType(numpyArray);
245  // check if the type of the numpy array matches the c++ type
246  PyArray_TYPES myEnum = typeEnumFromType<ValueType > ();
247  if (myEnum != pyArrayType) {
248  std::stringstream ss;
249  ss << "type mismatch:\n";
250  ss << "python type: " << printEnum(pyArrayType) << "\n";
251  ss << "c++ expected type : " << printEnum(myEnum);
252  PyErr_SetString(PyExc_ValueError, ss.str().c_str());
253  return 0;
254  }
255  if(DIM!=0){
256  const boost::python::tuple &shape = boost::python::extract<boost::python::tuple > (numpyArray.attr("shape"));
257  if(boost::python::len(shape)!=DIM){
258  std::stringstream ss;
259  ss << "dimension mismatch:\n";
260  ss << "python numpy dimension : " << boost::python::len(shape) << "\n";
261  ss << "c++ expected dimension : " << DIM;
262  PyErr_SetString(PyExc_ValueError, ss.str().c_str());
263  }
264  }
265  }
266  return obj_ptr;
267  }
268 
269  // Convert obj_ptr into a NumpyViewType
270 
271  static void construct(
272  PyObject* obj_ptr,
273  boost::python::converter::rvalue_from_python_stage1_data * data) {
274  // Extract the character data from the python string
275 
276  // Grab pointer to memory into which to construct the new NumpyViewType
277  void* storage = (
278  (boost::python::converter::rvalue_from_python_storage<NumpyViewType>*)
279  data)->storage.bytes;
280 
281  // in-place construct the new NumpyViewType using the character data
282  // extraced from the python object
283  //const numeric::array & numpyArray = extractConstNumericArray(obj_ptr);
284  new (storage) NumpyViewType(boost::python::object(boost::python::borrowed(obj_ptr)));
285  // Stash the memory chunk pointer for later use by boost.python
286  data->convertible = storage;
287  }
288 };
289 
290 
291 template<class VALUE_TYPE,size_t DIM>
293 
295 
296  static PyObject * convert(NumpyViewType numpyView ){
297  return numpyView.object().ptr();
298  }
299 };
300 
301 
302 template<class T,size_t DIM>
304  using namespace boost::python;
307 }
308 
309 
310 
311 
312 
313 }
314 }
315 
316 
317 #endif
318 
static PyObject * convert(NumpyViewType numpyView)
Definition: converter.hxx:296
boost::python::numeric::array objToArray(boost::python::object obj)
Definition: converter.hxx:116
boost::python::numeric::array extractConstNumericArray(PyObject *obj)
Definition: converter.hxx:213
The OpenGM namespace.
Definition: config.hxx:43
int numpyScalarTypeNumber(PyObject *obj)
Definition: converter.hxx:219
PyArray_TYPES getArrayType(NUMERIC_ARRAY arr)
Definition: converter.hxx:208
NPY_TYPES typeEnumFromType< float >(void)
Definition: converter.hxx:74
boost::python::list iteratorToList(ITERATOR iter, size_t size)
Definition: converter.hxx:189
boost::python::numeric::array iteratorToNumpy(ITERATOR iter, size_t size)
Definition: converter.hxx:198
boost::python::object get2dArray(const size_t size1, const size_t size2)
Definition: converter.hxx:93
std::string printEnum(PyArray_TYPES value)
Definition: converter.hxx:123
boost::python::object getArray(FORWARD_SHAPE_ITERATOR begin, FORWARD_SHAPE_ITERATOR end)
Definition: converter.hxx:101
NPY_TYPES typeEnumFromType< bool >(void)
Definition: converter.hxx:37
void initializeNumpyViewConverters()
Definition: converter.hxx:303
boost::python::tuple iteratorToTuple(ITERATOR iter, size_t size)
Definition: converter.hxx:154
static void construct(PyObject *obj_ptr, boost::python::converter::rvalue_from_python_stage1_data *data)
Definition: converter.hxx:271
boost::python::object get1dArray(const size_t size)
Definition: converter.hxx:86
NPY_TYPES typeEnumFromType< double >(void)
Definition: converter.hxx:78
static void * convertible(PyObject *obj_ptr)
Definition: converter.hxx:238
VALUE_TYPE * getCastedPtr(boost::python::object obj)
Definition: converter.hxx:111
OpenGM runtime error.
Definition: opengm.hxx:100
NPY_TYPES typeEnumFromType(void)
Definition: converter.hxx:30