Skip to content

Commit

Permalink
Merge branch 'dev' of https://github.com/gimli-org/gimli into dev
Browse files Browse the repository at this point in the history
  • Loading branch information
carsten-forty2 committed Sep 24, 2018
2 parents a9d5b46 + 3b3001f commit fa82cab
Show file tree
Hide file tree
Showing 7 changed files with 170 additions and 87 deletions.
122 changes: 79 additions & 43 deletions python/custom_rvalue.cpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
#include <typeinfo>

#include "boost/python/object.hpp" //len function
#include "boost/python/ssize_t.hpp" //ssize_t type definition
#include "boost/python/detail/none.hpp"
Expand Down Expand Up @@ -38,27 +40,51 @@ template < class ValueType > void * checkConvertibleSequenz(PyObject * obj){
// import_array2("Cannot import numpy c-api from pygimli hand_make_wrapper2", NULL);
// is obj is a sequence
if(!PySequence_Check(obj)){
__DC(obj << "\t !Object")
__DC(obj << "\t abborting no object")
return NULL;
}

// has the obj a len method
if (!PyObject_HasAttrString(obj, "__len__")){
__DC(obj << "\t !len")
__DC(obj << "\t abborting no len")
return NULL;
}

if (strcmp(obj->ob_type->tp_name, "numpy.ndarray") == 0){
__DC(obj << "\t numpy.ndarray ... okay")
__DC(obj << "\t numpy.ndarray to " << typeid(ValueType).name() << " " << typeid(bool).name()<< " " << typeid(float).name()<< "... okay")

if (typeid(ValueType) == typeid(GIMLI::Index)){

PyArrayObject *arr = (PyArrayObject *)obj;

if (PyArray_TYPE(arr) == NPY_BOOL){
__DC(obj << "\t Object is nd.array with dtype == bool* .. non convertable to GIMLI::IVector")
return NULL;
}
}

return obj;
}

bp::object py_sequence(bp::handle<>(bp::borrowed(obj)));

if (len(py_sequence) > 0) {
__DC(obj << "\t len: " << len(py_sequence) << " type: " << GIMLI::type(ValueType(0)))
__DC(obj << "\t len: " << len(py_sequence) << " type: " << GIMLI::type(ValueType(0)) << ": " << typeid(ValueType).name())
bp::object element = py_sequence[0];
__DC(obj << "\t seq[0]: " << element << " " << " type: " << GIMLI::type(ValueType(0)))
__DC(obj << "\t seq[0]: " << element << " is of type: " << element.ptr()->ob_type->tp_name)

if (typeid(ValueType) == typeid(GIMLI::Index)){
if (strcmp(element.ptr()->ob_type->tp_name, "bool") == 0) {
__DC(obj << "\t abborting: Index requested but sequence of "<< element.ptr()->ob_type->tp_name)
return NULL;
}
} else if (typeid(ValueType) == typeid(bool)){
// special check for BVector .. we oonly want to convert sequence of bool objects
if (strcmp(element.ptr()->ob_type->tp_name, "bool") != 0) {
__DC(obj << "\t abborting: bools requested but sequence of "<< element.ptr()->ob_type->tp_name)
return NULL;
}
}

bp::extract< ValueType > type_checker(element);
if (type_checker.check()){
Expand Down Expand Up @@ -150,7 +176,7 @@ struct PySequence2RVector{
/*! Check if the object is convertible */
static void * convertible(PyObject * obj){
__DC(obj << " -> RVector")
return checkConvertibleSequenz<double>(obj);
return checkConvertibleSequenz< double >(obj);
}

/*! Convert List[] or ndarray into RVector */
Expand Down Expand Up @@ -349,6 +375,32 @@ struct PySequence2IVector{
private:
};

struct PySequence2BVector{
static void * convertible(PyObject * obj){
__DC(obj << " -> BVector")
return checkConvertibleSequenz< bool >(obj);
}
static void construct(PyObject* obj, bp::converter::rvalue_from_python_stage1_data * data){
__DC(obj << "\t constructing BVector")
bp::object py_sequence(bp::handle<>(bp::borrowed(obj)));

typedef bp::converter::rvalue_from_python_storage< GIMLI::BVector> storage_t;

storage_t* the_storage = reinterpret_cast<storage_t*>(data);
void* memory_chunk = the_storage->storage.bytes;

GIMLI::BVector * vec = new (memory_chunk) GIMLI::BVector(len(py_sequence));
data->convertible = memory_chunk;
__DC(obj << "\t from list")
for (GIMLI::Index i = 0; i < vec->size(); i ++){
(*vec)[i] = PyArrayScalar_VAL(bp::object(py_sequence[i]).ptr(), Bool);

// __DC(i << " " << bp::object(py_sequence[i]) << " " << (*vec)[i])
//(*vec)[i] = bp::extract< bool >(py_sequence[i]);
}
}
};

struct PySequence2StdVectorRVector3{

/*! Check if the object is convertible */
Expand Down Expand Up @@ -464,44 +516,28 @@ struct Numpy2RMatrix{
private:
};

void * checkConvertibleNumpyIndex(PyObject * obj){
__DC(obj << "\tNumpyScalar -> Index")
if (!obj){
__DC(obj << "\t !Object")
return NULL;
}
if (PySequence_Check(obj)){
__DC(obj << "\t check is Sequenz : ")
return NULL;
}
if (PyObject_HasAttrString(obj, "dtype")){
if ((strcmp(obj->ob_type->tp_name, "numpy.float32") == 0) ||
(strcmp(obj->ob_type->tp_name, "numpy.float64") == 0)) {
__DC(obj << "\t Object is numpy.float .. non convert")
return NULL;
}
__DC(obj << "\t Object has dtype .. assuming numpy")
return obj;
} else {
__DC(obj << "\t Object no dtype")
return NULL;
}

return NULL;
}

template < class ValueType > void * checkConvertibleNumpyScalar(PyObject * obj){
__DC(obj << "\tNumpyScalar -> " + GIMLI::type(ValueType(0)))
if (!obj){
__DC(obj << "\t !Object")
__DC(obj << "\t abort check .. !Object")
return NULL;
}
if (PySequence_Check(obj)){
__DC(obj << "\t check is Sequenz : ")
__DC(obj << "\t abort check .. is Sequenz : ")
return NULL;
}
if (PyObject_HasAttrString(obj, "dtype")){
__DC(obj << "\t Object has dtype .. assuming numpy")

if (typeid(ValueType) == typeid(GIMLI::Index)){
if ((strcmp(obj->ob_type->tp_name, "numpy.float32") == 0) ||
(strcmp(obj->ob_type->tp_name, "numpy.float64") == 0)) {
__DC(obj << "\t Object is numpy.float* .. non convert to GIMLI::Index")
return NULL;
}
}

return obj;
} else {
__DC(obj << "\t Object no dtype")
Expand Down Expand Up @@ -568,8 +604,8 @@ struct Numpy2Long{
//template <typename T, NPY_TYPES NumPyScalarType>
struct Numpy2ULong{
static void * convertible(PyObject * obj){
__DC(obj << " -> Index")
return checkConvertibleNumpyIndex(obj);
__DC(obj << " -> Index(Numpy2ULong)")
return checkConvertibleNumpyScalar< GIMLI::Index >(obj);
}
static void construct(PyObject* obj, bp::converter::rvalue_from_python_stage1_data * data){
return convertFromNumpyScalar< GIMLI::Index >(obj, data);
Expand All @@ -580,7 +616,7 @@ struct Numpy2ULong{
//template <typename T, NPY_TYPES NumPyScalarType>
struct Numpy2Int{
static void * convertible(PyObject * obj){
__DC(obj << " -> int")
__DC(obj << " -> int(Numpy2Int)")
return checkConvertibleNumpyScalar< GIMLI::int32 >(obj);
}
static void construct(PyObject* obj, bp::converter::rvalue_from_python_stage1_data * data){
Expand All @@ -592,7 +628,7 @@ struct Numpy2Int{
//template <typename T, NPY_TYPES NumPyScalarType>
struct Numpy2UInt{
static void * convertible(PyObject * obj){
__DC(obj << " -> uint")
__DC(obj << " -> uint(Numpy2UInt)")
return checkConvertibleNumpyScalar< GIMLI::uint32 >(obj);
}
static void construct(PyObject* obj, bp::converter::rvalue_from_python_stage1_data * data){
Expand All @@ -604,7 +640,7 @@ struct Numpy2UInt{
//template <typename T, NPY_TYPES NumPyScalarType>
struct Numpy2Double{
static void * convertible(PyObject * obj){
__DC(obj << " -> double")
__DC(obj << " -> double(Numpy2Double)")
return checkConvertibleNumpyScalar< double >(obj);
}
static void construct(PyObject* obj, bp::converter::rvalue_from_python_stage1_data * data){
Expand Down Expand Up @@ -663,11 +699,11 @@ void register_pysequence_to_cvector_conversion(){
bp::type_id< GIMLI::Vector< GIMLI::Complex > >());
}

// void register_pysequence_to_bvector_conversion(){
// bp::converter::registry::push_back(& r_values_impl::PySequence2BVector::convertible,
// & r_values_impl::PySequence2BVector::construct,
// bp::type_id< GIMLI::Vector< bool > >());
// }
void register_pysequence_to_bvector_conversion(){
bp::converter::registry::push_back(& r_values_impl::PySequence2BVector::convertible,
& r_values_impl::PySequence2BVector::construct,
bp::type_id< GIMLI::Vector< bool > >());
}
void register_pysequence_to_StdVectorRVector3_conversion(){
bp::converter::registry::push_back(& r_values_impl::PySequence2StdVectorRVector3::convertible,
& r_values_impl::PySequence2StdVectorRVector3::construct,
Expand Down
1 change: 1 addition & 0 deletions python/generate_pygimli_code.py
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,7 @@ def generate(defined_symbols, extraIncludes):
'register_pysequence_to_rvector_conversion',
#'register_pysequence_to_cvector_conversion', .. will not work
'register_pysequence_to_ivector_conversion',
'register_pysequence_to_bvector_conversion',
'register_pysequence_to_indexvector_conversion',
'register_pysequence_to_r3vector_conversion',
'register_pysequence_to_StdVectorRVector3_conversion',
Expand Down
59 changes: 44 additions & 15 deletions python/pygimli/testing/test_RValueConverter.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,41 @@ def test_NumpyToIndexArray(self):
self.assertEqual(a.size(), len(x))
self.assertEqual(pg.sum(a), sum(x))

def test_NumpyToIVector(self):
"""Implemented in custom_rvalue.cpp."""
x = np.array(range(-10, 10))
a = pg.IVector(x)
self.assertEqual(a.size(), len(x))
self.assertEqual(pg.sum(a), sum(x))

x = np.arange(-10, 10, dtype=np.int64)
a = pg.IVector(x)
self.assertEqual(a.size(), len(x))
self.assertEqual(pg.sum(a), sum(x))

x = np.arange(-10, 10, dtype="int")
a = pg.IVector(x)
self.assertEqual(a.size(), len(x))
self.assertEqual(pg.sum(a), sum(x))

x = np.array([-10, 100], dtype="int")
a = pg.IVector(x)
self.assertEqual(a.size(), len(x))
self.assertEqual(pg.sum(a), sum(x))

x = np.arange(10, dtype=np.long)
a = pg.IVector(x)
self.assertEqual(a.size(), len(x))
self.assertEqual(pg.sum(a), sum(x))
self.assertEqual(pg.sum(x), sum(x))

def test_NumpyToBVector(self):
"""Implemented in custom_rvalue.cpp."""
x = np.array(range(-10, 10), dtype=float)
b = pg.BVector(x > 0.)
self.assertEqual(b[10], False)
self.assertEqual(b[11], True)

def test_NumpyToRVector(self):
"""Implemented in custom_rvalue.cpp."""
x = np.arange(0, 1., 0.2)
Expand All @@ -103,20 +138,13 @@ def test_NumpyToRVector(self):

x = np.arange(10, dtype=np.long)
a = pg.RVector(x)

self.assertEqual(a.size(), len(x))
self.assertEqual(pg.sum(a), sum(x))

self.assertEqual(pg.sum(x), sum(x))

def test_NumpyToIVector(self):
x = np.arange(10, dtype=np.long)
a = pg.IVector(x)
self.assertEqual(a.size(), len(x))
self.assertEqual(pg.sum(a), sum(x))

self.assertEqual(pg.sum(x), sum(x))



def test_NumpyToCVector(self):
pass
# will not work .. until an idea how to choose right api for function with and RVector and CVector, e.g. sum()
Expand Down Expand Up @@ -180,7 +208,7 @@ def test_BVectorToNumpy(self):
v = pg.RVector(10, 1)
b = (v == 1)
self.assertEqual(type(b), pg.BVector)

v = pg.RVector(10, 1.1)
b = (v == 1.1)
self.assertEqual(type(b), pg.BVector)
Expand Down Expand Up @@ -269,7 +297,7 @@ def test_NumpyToScalar(self):
np.testing.assert_equal(sum(x - 1.0), 0.0)
np.testing.assert_equal(sum(x - np.float32(1)), 0.0)
np.testing.assert_equal(sum(x - np.float64(1)), 0.0)

# HarmonicModelling(size_t nh, const RVector & tvec);
pg.HarmonicModelling(np.int32(1), x);
pg.HarmonicModelling(np.uint32(1), x);
Expand All @@ -288,16 +316,17 @@ def test_NumpyToScalar(self):
np.testing.assert_equal(x -1 , pg.Pos(0.0, 0.0, 0.0))
np.testing.assert_equal(x - np.float32(1), pg.Pos(0.0, 0.0, 0.0))
np.testing.assert_equal(x - np.float64(1), pg.Pos(0.0, 0.0, 0.0))


if __name__ == '__main__':
pg.setDeepDebug(0)
test = TestRVectorMethods()

#test.test_IndexArrayToNumpy()
#test.test_NumpyToIVector()
#test.test_NumpyToScalar()
#exit()
# test.test_NumpyToBVector()
# exit()
# test.test_BVectorToNumpy()
# test.test_NumpyToIVector()
# test.test_NumpyToRVector()
Expand Down
18 changes: 4 additions & 14 deletions python/pygimli/testing/test_XVector.py
Original file line number Diff line number Diff line change
Expand Up @@ -301,19 +301,9 @@ def testComparison(self):


if __name__ == '__main__':

# s = TestRVectorMethods()
# pg.setDebug(1)
# s.test_IVectorOP()
# pg.setDeepDebug(1)
# t = TestRVectorMethods()
# # t.test_IVectorOP()
# t.test_Slices()

unittest.main()


#suite.addTest(TestRVectorMethods("test_R3VectorIndex"))

###suite.addTest(TestRVectorMethods("test_RVectorOP"))
##suite.addTest(TestRVectorMethods("test_IndexAccess"))
###suite.addTest(TestRVectorMethods("test_Slices"))

#runner = unittest.TextTestRunner()
#runner.run(suite)
Loading

0 comments on commit fa82cab

Please sign in to comment.