in source/neuropod/bindings/python_bindings.cc [102:139]
std::shared_ptr<NeuropodTensor> tensor_from_numpy(NeuropodTensorAllocator &allocator, py::array array)
{
// Make sure the array is contiguous and aligned
// NOLINTNEXTLINE(readability-implicit-bool-conversion, hicpp-signed-bitwise)
if (!(array.flags() & py::detail::npy_api::constants::NPY_ARRAY_C_CONTIGUOUS_) ||
!(array.flags() & py::detail::npy_api::constants::NPY_ARRAY_ALIGNED_))
{
SPDLOG_WARN("Expected numpy array to be contiguous and aligned; converting...");
array = py::array::ensure(array,
py::detail::npy_api::constants::NPY_ARRAY_C_CONTIGUOUS_ |
py::detail::npy_api::constants::NPY_ARRAY_ALIGNED_);
}
auto ndims = array.ndim();
auto dims = array.shape();
auto dtype = get_array_type(array);
auto data = array.mutable_data();
// Capture the array in our deleter so it doesn't get deallocated
// until we're done
auto to_delete = std::make_shared<py::array>(array);
auto deleter = [to_delete](void *unused) mutable {
py::gil_scoped_acquire gil;
to_delete.reset();
};
// Create a vector with the shape info
std::vector<int64_t> shape(&dims[0], &dims[ndims]);
// Handle string tensors
if (dtype == STRING_TENSOR)
{
return tensor_from_string_numpy(allocator, array, shape);
}
// Wrap the data from the numpy array
return allocator.tensor_from_memory(shape, dtype, data, deleter);
}