Skip to content

Commit

Permalink
source and sink working in python
Browse files Browse the repository at this point in the history
  • Loading branch information
burgerdev committed Jan 5, 2014
1 parent ab3263b commit 51ed356
Show file tree
Hide file tree
Showing 7 changed files with 206 additions and 26 deletions.
75 changes: 68 additions & 7 deletions blockedarray/adapters.py
@@ -1,6 +1,7 @@

import numpy
import numpy as np
from _blockedarray import Source3U8 as Source
from _blockedarray import Sink3U8 as Sink


class SourceABC(Source):
Expand All @@ -10,7 +11,7 @@ def __init__(self):
'''
* selects only the region of interest given from the
* underlying data source. When readBlock() is used, the coordinates
* are relative to roi.q
* are relative to roi[0]
'''
def pySetRoi(self, roi):
raise NotImplementedError
Expand All @@ -25,18 +26,78 @@ def pyReadBlock(self, roi, output):
#return True


class ExampleSource(SourceABC):
class SinkABC(Sink):
def __init__(self):
super(ExampleSource, self).__init__()
super(SinkABC, self).__init__()

def pyWriteBlock(self, roi, block):
raise NotImplementedError
#return True


class DummySource(SourceABC):
def __init__(self):
super(DummySource, self).__init__()

def pySetRoi(self, roi):
pass

def pyShape(self):
return numpy.asarray((100, 100, 10), dtype=numpy.long)
return np.asarray((100, 100, 10), dtype=np.long)

def pyReadBlock(self, roi, output):
print(roi)
print(output)
output[...] = 0
return True


class ExampleSource(SourceABC):
def __init__(self, vol):
# the call to super() is super-important!
super(ExampleSource, self).__init__()
self._vol = vol
self._p = np.zeros((len(vol.shape),), dtype=np.long)
self._q = np.asarray(vol.shape, dtype=np.long)

def pySetRoi(self, roi):
assert len(roi) == 2
self._p = np.asarray(roi[0], dtype=np.long)
self._q = np.asarray(roi[1], dtype=np.long)

def pyShape(self):
return self._vol.shape

def pyReadBlock(self, roi, output):
assert len(roi) == 2
roiP = np.asarray(roi[0])
roiQ = np.asarray(roi[1])
p = self._p + roiP
q = p + roiQ - roiP
if np.any(q > self._q):
raise IndexError("Requested roi is too large for selected "
"roi (previous call to setRoi)")
s = _roi2slice(p, q)
output[...] = self._vol[s]
return True


class ExampleSink(SinkABC):
def __init__(self):
super(ExampleSink, self).__init__()
self.vol = None

def pyWriteBlock(self, roi, block):
assert len(roi) == 2
if self.vol is None:
shape = _v2tup(self.shape)
self.vol = np.zeros(shape, dtype=np.uint8)
s = _roi2slice(roi[0], roi[1])
self.vol[s] = block


def _v2tup(v, d=3):
return tuple([v[i] for i in range(d)])


def _roi2slice(p, q):
s = [slice(p[i], q[i]) for i in range(len(p))]
return tuple(s)
53 changes: 44 additions & 9 deletions blockedarray/adapters_py.cxx
Expand Up @@ -22,18 +22,24 @@ using namespace BW;


/* ROI conversion */

template<int N>
boost::python::list tinyVecToList(const typename Roi<N>::V &vec)
{
boost::python::object iterator = boost::python::iterator<typename Roi<N>::V>()(vec);
return boost::python::list(iterator);
}

template<int N>
struct Roi_to_python_tuple
{
typedef typename Roi<N>::V TinyVec;
static PyObject* convert(const Roi<N> &roi)
{
// p
boost::python::object iteratorP = boost::python::iterator<TinyVec>()(roi.p);
boost::python::list p(iteratorP);
boost::python::list p = tinyVecToList<N>(roi.p);
// q
boost::python::object iteratorQ = boost::python::iterator<TinyVec>()(roi.q);
boost::python::list q(iteratorQ);
boost::python::list q = tinyVecToList<N>(roi.q);

boost::python::tuple t = boost::python::make_tuple(p, q);
return boost::python::incref(t.ptr());
Expand Down Expand Up @@ -102,7 +108,7 @@ struct PySourceABC : Source<N,T>, boost::python::wrapper<Source<N,T> >
};

template<int N, class T>
class PySinkABC : Sink<N,T> {
struct PySinkABC : Sink<N,T>, boost::python::wrapper<Sink<N,T> > {
public:
typedef typename Roi<N>::V V;

Expand All @@ -111,17 +117,35 @@ class PySinkABC : Sink<N,T> {

bool writeBlock(Roi<N> roi, const vigra::MultiArrayView<N,T>& block)
{
bool ret;

vigra::NumpyArray<N,T> tempArray(block);

return this->pyWriteBlock(roi, tempArray);
}

bool pyWriteBlock(Roi<N> roi, const vigra::NumpyArray<N,T>& block)
{
return this->get_override("pyReadBlock")(roi, block);
return this->get_override("pyWriteBlock")(roi, block);
};

/* Accessor functions for the shapes */
boost::python::list getShape() const
{
return tinyVecToList<N>(this->shape_);
}

void setShape(V shape)
{
this->shape_ = shape;
}

boost::python::list getBlockShape() const
{
return tinyVecToList<N>(this->blockShape_);
}

void setBlockShape(V shape)
{
this->blockShape_ = shape;
}
};


Expand All @@ -135,10 +159,21 @@ void exposeSource(const char* exposedName) {
.def("pyShape", pure_virtual(&PySourceABC<N,T>::pyShape))
.def("pyReadBlock", pure_virtual(&PySourceABC<N,T>::pyReadBlock))
;
}

template<int N, class T>
void exposeSink(const char* exposedName) {
using namespace boost::python;

class_<PySinkABC<N,T>, boost::noncopyable>(exposedName)
.def("pyWriteBlock", pure_virtual(&PySinkABC<N,T>::pyWriteBlock))
.add_property("shape", &PySinkABC<N,T>::getShape, &PySinkABC<N,T>::setShape)
.add_property("blockShape", &PySinkABC<N,T>::getBlockShape, &PySinkABC<N,T>::setBlockShape)
;
}

void export_adapters() {
exposeSource<3,vigra::UInt8>("Source3U8");
exposeSink<3,vigra::UInt8>("Sink3U8");
registerConverters();
}
52 changes: 52 additions & 0 deletions blockedarray/test_adapters.py
@@ -0,0 +1,52 @@
import numpy as np
import unittest

from adapters import ExampleSource, ExampleSink


class TestSource(unittest.TestCase):

def setUp(self):
self.vol = np.random.randint(0, 2**32, (100, 100, 10)).astype(np.uint32)

def testExampleSource(self):
vol = self.vol
s = ExampleSource(vol)

roi = [np.zeros((len(vol.shape),)), vol.shape]
newVol = np.zeros(vol.shape, dtype=np.uint32)
assert s.pyReadBlock(roi, newVol)
assert np.all(vol == newVol)

def testRoi(self):
vol = self.vol
s = ExampleSource(vol)

reqRoi = [(50, 50, 2), (70, 70, 4)]
s.pySetRoi(reqRoi)
roi = [(0, 0, 0), (20, 20, 2)]
newVol = np.zeros((20, 20, 2), dtype=np.uint32)
assert s.pyReadBlock(roi, newVol)
assert np.all(vol[50:70, 50:70, 2:4] == newVol)

def testRoi2(self):
vol = self.vol
s = ExampleSource(vol)
roi = [(0, 0, 2), (20, 20, 4)]
newVol = np.zeros((20, 20, 2), dtype=np.uint32)
assert s.pyReadBlock(roi, newVol)


class TestSink(unittest.TestCase):

def setUp(self):
pass

def testExampleSink(self):
s = ExampleSink()
s.shape = (100, 100, 10)
s.blockShape = (10, 10, 10)
s.pyWriteBlock([(15, 20, 2), (30, 30, 6)],
np.ones((15, 10, 4), dtype=np.uint8))

assert np.all(s.vol[15:30, 20:30, 2:6] == 1)
8 changes: 0 additions & 8 deletions blockedarray/test_blockedarray.py
Expand Up @@ -2,7 +2,6 @@
import vigra
import h5py

from adapters import ExampleSource
from _blockedarray import *

def rw(ba):
Expand Down Expand Up @@ -76,13 +75,6 @@ def test1():
ba.setCompressionEnabled(False)


def testConnectedComponents():
CC = dim3.ConnectedComponents
s = ExampleSource()
v = numpy.asarray((10, 10, 10), dtype=numpy.long)
cc = CC(s, v)
#cc = CC(s)

if __name__ == "__main__":
test1()
print "success"
38 changes: 38 additions & 0 deletions blockedarray/test_connectedcomponents.py
@@ -0,0 +1,38 @@
import numpy as np
import unittest

from adapters import DummySource, ExampleSource
from _blockedarray import dim3


class TestConnectedComponents(unittest.TestCase):

def setUp(self):
shape = (100, 100, 100)
self.blockShape = (10, 10, 10)
vol = np.zeros(shape, dtype=np.uint8)
vol[7:12, 7:12, 7:12] = 42
vol[:, :, 72:75] = 111
vol[:, 72:75, :] = 111
self.vol = vol

def testBlockShape(self):
CC = dim3.ConnectedComponents
s = DummySource()

v = (10, 10, 10)
cc = CC(s, v)

v = np.asarray((10, 10, 10))
cc = CC(s, v)

v = np.asarray((10, 10, 10), dtype=np.long)
cc = CC(s, v)

v = np.asarray((10, 10, 10), dtype=np.int)
cc = CC(s, v)

def testCC(self):
CC = dim3.ConnectedComponents
s = ExampleSource(self.vol)
assert CC(s, self.blockShape)
4 changes: 3 additions & 1 deletion include/bw/sink.h
Expand Up @@ -44,13 +44,15 @@ class Sink {
public:
typedef typename Roi<N>::V V;

Sink() {}
Sink() {};
virtual ~Sink() {};

/* has to be called before any calls to writeBlock */
void setShape(V shape) {
shape_ = shape;
}

/* has to be called before any calls to writeBlock */
void setBlockShape(V shape) {
blockShape_ = shape;
}
Expand Down
2 changes: 1 addition & 1 deletion include/bw/source.h
Expand Up @@ -44,7 +44,7 @@ class Source {
public:
typedef typename Roi<N>::V V;

Source() {}
Source() {};
virtual ~Source() {};

/**
Expand Down

0 comments on commit 51ed356

Please sign in to comment.