Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

avoid copying data to Python but using numpy::frombuffer #717

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions src/xSTIR/cSTIR/cstir.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -694,6 +694,20 @@ void* cSTIR_get_ProjDataInfo(void* ptr_acq)
CATCH;
}

extern "C"
void* cSTIR_AcquisitionDataInMemory_get_buffer(void* adim_ptr, size_t out_ptr)
{
try {
SPTR_FROM_HANDLE(PETAcquisitionDataInMemory, adim_sptr, adim_ptr);
stir::ProjDataInMemory &pdim =
dynamic_cast<stir::ProjDataInMemory&>(*adim_sptr->data());
float* out_float_ptr = (float*)out_ptr;
out_float_ptr = pdim.begin().base();
return (void*) new DataHandle;
}
CATCH;
}

extern "C"
void* cSTIR_setupFBP2DReconstruction(void* ptr_r, void* ptr_i)
{
Expand Down
1 change: 1 addition & 0 deletions src/xSTIR/cSTIR/include/sirf/STIR/cstir.h
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ extern "C" {
(void* ptr_acq, const void * ptr_from);
void* cSTIR_writeAcquisitionData(void* ptr_acq, const char* filename);
void* cSTIR_get_ProjDataInfo(void* ptr_acq);
void* cSTIR_AcquisitionDataInMemory_get_buffer(void* adim_ptr, PTR_FLOAT out_ptr);

// Reconstruction methods
void* cSTIR_setupFBP2DReconstruction(void* ptr_r, void* ptr_i);
Expand Down
21 changes: 18 additions & 3 deletions src/xSTIR/pSTIR/STIR.py.in
Original file line number Diff line number Diff line change
Expand Up @@ -722,9 +722,18 @@ class AcquisitionData(DataContainer):
- number of tangential positions.
'''
assert self.handle is not None
array = numpy.ndarray(self.dimensions(), dtype = numpy.float32)
try_calling(pystir.cSTIR_getAcquisitionData\
(self.handle, array.ctypes.data))
# If using file storage scheme, create numpy array and copy data
if self.get_storage_scheme() == "file":
array = numpy.ndarray(self.dimensions(), dtype = numpy.float32)
try_calling(pystir.cSTIR_getAcquisitionData\
(self.handle, array.ctypes.data))
# If using memory, use a buffer and have a shared object
else:
buffer = ?
try_calling(pystir.cSTIR_AcquisitionDataInMemory_get_buffer\
(self.handle, buffer))
array = numpy.frombuffer(buffer, dtype=numpy.float32)
Comment on lines +732 to +735
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do not see how this can possibly work. However you define buffer, pystir.cSTIR_AcquisitionDataInMemory_get_buffer can only give you an address in memory, but numpy.frombuffer needs to know the size of memory represented by the buffer to be able to handle that memory as numpy array data.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I haven't done it here, but you can give the number of elements with count:

numpy.frombuffer(buffer, dtype=float, count=-1, offset=0)

And obviously we know how many elements our sinogram contains.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The problem is that the first argument to frombuffer should be of type buffer_like (see here). I have no idea how to do this, but the address to the first float in C++ somehow needs to be converted to this buffer_like object in Python. Searching online, it looks like it's possible with SWIG, but I'm not sure how to do it in SIRF's setup.

array.shape = self.dimensions()
return array
def fill(self, value):
'''
Expand All @@ -744,6 +753,12 @@ class AcquisitionData(DataContainer):
v = value.astype(numpy.float32)
if not v.flags['C_CONTIGUOUS']:
v = numpy.ascontiguousarray(v)
# If storage_scheme==memory AND numpy array has same address as
# C++ buffer, nothing to do!
# if self.get_storage_scheme() == 'memory' and :
# return

# Else, copy from numpy to c++
try_calling(pystir.cSTIR_setAcquisitionData\
(self.handle, v.ctypes.data))
elif isinstance(value, AcquisitionData):
Expand Down