SciSharp / NumSharp

High Performance Computation for N-D Tensors in .NET, similar API to NumPy.
https://github.com/SciSharp
Apache License 2.0
1.36k stars 189 forks source link

is there any way to convert NumSharp.NDArray to Numpy.NDarray? #383

Open lelelemonade opened 4 years ago

Nucs commented 4 years ago

Me and @henon have collaborated just two days ago on a solution for that, The trick is to create a python scope, load a script that takes in a pointer-length and returns an np.ndarray Remember! you have to keep reference to the original NDArray, otherwise the NDArray will be disposed and will release the memory. (@henon is there a tag field we can use in NDarray?)

Note: the code below is psuedo, the rest of the code can be found here: ConsoleApp9.zip

numpy_interop.py as embedded resource

import numpy as np
import ctypes

def to_numpy(ptr, bytes, dtype, shape):
    return np.frombuffer((ctypes.c_uint8*(bytes)).from_address(ptr), dtype).reshape(shape)

PythonExtensions.cs

public static class PythonExtensions {

    ...
    private static PyScope NumpyInteropScope;
    private static PyObject NumpyConverter;

    public static unsafe NDarray ToNumpyNET(this NDArray nd) {
        using (Py.GIL()) {
            if (NumpyInteropScope == null) {
                NumpyInteropScope = Py.CreateScope();
                NumpyInteropScope.ExecResource("numpy_interop.py");
                NumpyConverter = NumpyInteropScope.GetFunction("to_numpy");
            }

            return new NDarray(NumpyConverter.Invoke(new PyLong((long) nd.Unsafe.Address),
                new PyLong(nd.size * nd.dtypesize),
                new PyString(nd.dtype.Name.ToLowerInvariant()),
                new PyTuple(nd.shape.Select(dim => (PyObject) new PyLong(dim)).ToArray())));
        }
    }
}

main.cs

using numsharp_np = NumSharp.np;
using numpy_np = Numpy.np;
static void Main(string[] args) {
    var numsharp_nd = numsharp_np.arange(10);
    var numpy_nd = numsharp_nd.ToNumpyNET();
    numpy_nd[1] = (NDarray) 5;
    Debug.Assert(numsharp_nd[1].array_equal(5));
    Console.WriteLine("numsharp_nd[1].array_equal(5) is indeed true!");
}
Nucs commented 4 years ago

Added some changes that will make sure the NDarray will hold reference to the NDArray as long as the PyObject doesnt change internally.

ConsoleApp9.zip

henon commented 4 years ago

Remember! you have to keep reference to the original NDArray, otherwise the NDArray will be disposed and will release the memory. (@henon is there a tag field we can use in NDarray?)

Not yet, but I will add one in Numpy.NET and support this.

davidvct commented 1 year ago

Hi, could you provide instruction on how to use the ConsoleApp9.zip? And does it able to convert Numpy array back to NumSharp array?

henon commented 1 year ago

@davidvct, if I remember correctly I have added support for copying data to and from Numpy.NET like @Nucs did in this solution. Read this to see how: https://github.com/SciSharp/Numpy.NET#create-a-numpy-array-from-a-c-array-and-vice-versa