Skip to content

Commit

Permalink
introduced ROI interface to adapters, better roi interface
Browse files Browse the repository at this point in the history
  • Loading branch information
burgerdev committed Mar 25, 2014
1 parent 83207e5 commit fcdf001
Show file tree
Hide file tree
Showing 8 changed files with 70 additions and 38 deletions.
27 changes: 19 additions & 8 deletions blockedarray/adapters.py
Expand Up @@ -4,9 +4,23 @@
import numpy as np
from _blockedarray import *


# This file contains examples for using the Source and Sink classes from
# blockedarray. These should be viewed as guidelines on how to use the exported
# interfaces
# dim[2|3].Source[U|S][8|16|32|64]
# dim[2|3].Sink[U|S][8|16|32|64]
# The ABC classes are for reference on what methods are exposed, the Example
# classes show how the base classes can be used. There is a complete workflow
# for blockwise connected components in the test file
# test_connectedcomponents.py


# examples deal with 8bit image input and 32bit image output
_Source = dim3.PySourceU8
_Sink = dim3.PySinkU32


## Source Interface
#
# This class provides the python interface to the C++ class `BW::Source`. If
Expand Down Expand Up @@ -92,17 +106,15 @@ def __init__(self, vol):
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)
self._p = np.asarray(roi.p, dtype=np.long)
self._q = np.asarray(roi.q, 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])
roiP = np.asarray(roi.p)
roiQ = np.asarray(roi.q)
p = self._p + roiP
q = p + roiQ - roiP
if np.any(q > self._q):
Expand All @@ -119,12 +131,11 @@ def __init__(self):
self.vol = None

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


Expand Down
10 changes: 4 additions & 6 deletions blockedarray/adapters_py.cxx
Expand Up @@ -94,7 +94,6 @@ struct PySinkABC : Sink<N,T>, boost::python::wrapper<Sink<N,T> > {
};


/* UNNEEDED
V getShape() const
{
return this->shape_;
Expand All @@ -105,16 +104,15 @@ struct PySinkABC : Sink<N,T>, boost::python::wrapper<Sink<N,T> > {
this->shape_ = shape;
}

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

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


Expand All @@ -131,8 +129,8 @@ void exportSpecificSourceAdapter(std::string suffix) {

class_<PySinkABC<N,T>, boost::noncopyable>(("PySink" + suffix).c_str())
.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)
.add_property("shape", &PySinkABC<N,T>::getShape, &PySinkABC<N,T>::setShape)
.add_property("blockShape", &PySinkABC<N,T>::getBlockShape, &PySinkABC<N,T>::setBlockShape)
;
}

Expand Down
10 changes: 6 additions & 4 deletions blockedarray/blockwisecc_py.cxx
Expand Up @@ -83,10 +83,12 @@ void exportRoiForDim()
typedef typename Roi<N>::V V;

class_< Roi<N> >("Roi", init<V,V>())
.def_readwrite("p", &Roi<N>::p)
.def_readwrite("q", &Roi<N>::p)
.def("getP", &Roi<N>::getP)
.def("getQ", &Roi<N>::getQ)
//.def_readwrite("p", &Roi<N>::p)
//.def_readwrite("q", &Roi<N>::p)
//.def("getP", &Roi<N>::getP)
//.def("getQ", &Roi<N>::getQ)
.add_property("p", &Roi<N>::getP, &Roi<N>::setP)
.add_property("q", &Roi<N>::getQ, &Roi<N>::setQ)
;
}

Expand Down
35 changes: 19 additions & 16 deletions blockedarray/opBlockedConnectedComponents.py
Expand Up @@ -10,6 +10,10 @@
from _blockedarray import dim2, dim3


## compute connected components blockwise
#
# Input must be 'xyzct' so this operator can be wrapped with
# lazyflow.OpLabelVolume
class OpBlockedConnectedComponents(OpNonLazyCC):
name = "OpBlockedConnectedComponents"
supportedDtypes = [np.uint8, np.uint32]
Expand Down Expand Up @@ -50,8 +54,8 @@ def pySetRoi(self, roi):
def pyShape(self):
return shape
def pyReadBlock(self, roi, block):
start = roi.getP() + (c, t)
stop = roi.getQ() + (c+1, t+1)
start = roi.p + (c, t)
stop = roi.q + (c+1, t+1)
subr = SubRegion(self._slot, start=start, stop=stop)
block[:] = self._slot.get(subr).wait()[..., 0, 0]
return True
Expand All @@ -67,28 +71,27 @@ def __init__(self, *args, **kwargs):
self._cache = kwargs['cache']
del kwargs['cache']
super(TempSink, self).__init__(*args, **kwargs)
self.shape = _v2tup(self._cache.Input.meta.shape)
self.blockShape = _v2tup(self._cache.BlockShape.value)
def pyWriteBlock(self, roi, block):
block = vigra.taggedView(block, axistags='xyz')
block = block.withAxes(*'xyzct')
start = roi.getP() + (c, t)
stop = roi.getQ() + (c+1, t+1)
start = roi.p + (c, t)
stop = roi.q + (c+1, t+1)
subr = SubRegion(self._cache.Input, start=start, stop=stop)
self._cache.setInSlot(self._cache.Input, (), subr, block)
return True

return TempSink(cache=self._cache)

def setupOutputs(self):
super(OpBlockedConnectedComponents, self).setupOutputs()
assert len(self.Input.meta.shape) == 5, "Input must be 5d"
if self.Input.meta.axistags:
# if axistags are given, they must be xyzct
s = "".join(self.Input.meta.getAxisKeys())
assert s == "xyzct", "Input must be in xyzct order, if any"

def printParents(obj, indent=0):
def printIndented(s):
print("{}{}".format(" "*indent, s))
if type(obj) != type:
print("Class hierarchy for {} (is a {})".format(obj, type(obj)))
printParents(type(obj))
else:
if indent > 15:
return
printIndented(obj)
for sub in obj.__bases__:
printParents(sub, indent=indent+1)

def _v2tup(v, d=3):
return tuple([int(v[i]) for i in range(d)])
3 changes: 2 additions & 1 deletion blockedarray/testOpBlockedConnectedComponents.py
Expand Up @@ -74,5 +74,6 @@ class TestSimpleThings(unittest.TestCase):
def testRoi(self):
from blockedarray import dim3
roi = dim3.Roi((0,0,0), (2,3,4))
p = roi.getP()
p = roi.p
assert isinstance(p, tuple)

11 changes: 9 additions & 2 deletions blockedarray/test_adapters.py
Expand Up @@ -2,6 +2,7 @@
import unittest

from adapters import ExampleSource, ExampleSink
from _blockedarray import dim3


class TestSource(unittest.TestCase):
Expand All @@ -13,7 +14,8 @@ def testExampleSource(self):
vol = self.vol
s = ExampleSource(vol)

roi = [np.zeros((len(vol.shape),)), vol.shape]
roi = dim3.Roi((0,)*len(vol.shape),
tuple(vol.shape))
newVol = np.zeros(vol.shape, dtype=np.uint32)
assert s.pyReadBlock(roi, newVol)
assert np.all(vol == newVol)
Expand All @@ -23,8 +25,10 @@ def testRoi(self):
s = ExampleSource(vol)

reqRoi = [(50, 50, 2), (70, 70, 4)]
reqRoi = dim3.Roi(reqRoi[0], reqRoi[1])
s.pySetRoi(reqRoi)
roi = [(0, 0, 0), (20, 20, 2)]
roi = dim3.Roi(roi[0], roi[1])
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)
Expand All @@ -33,6 +37,7 @@ def testRoi2(self):
vol = self.vol
s = ExampleSource(vol)
roi = [(0, 0, 2), (20, 20, 4)]
roi = dim3.Roi(roi[0], roi[1])
newVol = np.zeros((20, 20, 2), dtype=np.uint32)
assert s.pyReadBlock(roi, newVol)

Expand All @@ -46,7 +51,9 @@ def testExampleSink(self):
s = ExampleSink()
s.shape = (100, 100, 10)
s.blockShape = (10, 10, 10)
s.pyWriteBlock([(15, 20, 2), (30, 30, 6)],
roi = [(15, 20, 2), (30, 30, 6)]
roi = dim3.Roi(roi[0], roi[1])
s.pyWriteBlock(roi,
np.ones((15, 10, 4), dtype=np.uint8))

assert np.all(s.vol[15:30, 20:30, 2:6] == 1)
2 changes: 1 addition & 1 deletion blockedarray/test_connectedcomponents.py
Expand Up @@ -10,7 +10,7 @@
from _blockedarray import dim3


CC = dim3.ConnectedComponents
CC = dim3.ConnectedComponentsU8

class TestConnectedComponents(unittest.TestCase):

Expand Down
10 changes: 10 additions & 0 deletions include/bw/roi.h
Expand Up @@ -192,6 +192,16 @@ class Roi {
{
return q;
}

void setP(V p)
{
this->p = p;
}

void setQ(V q)
{
this->q = q;
}

V p;
V q;
Expand Down

0 comments on commit fcdf001

Please sign in to comment.