Skip to content

Does np.interp Implemented? #132

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

Closed
ElinLiu0 opened this issue Feb 23, 2025 · 15 comments
Closed

Does np.interp Implemented? #132

ElinLiu0 opened this issue Feb 23, 2025 · 15 comments

Comments

@ElinLiu0
Copy link

Hi:
i've there's a testing code at:

public void interpTest()

Yet when i wanna using this function in project,it raised:

Image
It raise it's not defined.

@henon
Copy link
Contributor

henon commented Feb 24, 2025

It is not implemented yet and if you look closely you will notice that the code in the test case (which is auto-generated by the way) everything is commented out using #if TODO

I am looking into it if this can be implemented easily.

@ElinLiu0
Copy link
Author

Got it,I've use DeepSeek to trying implement this,hope it works as expected.

Temp Close.

@henon
Copy link
Contributor

henon commented Feb 25, 2025

Can you share your solution please?

@ElinLiu0
Copy link
Author

using System;
using System.Collections.Generic;
using System.Text;

namespace ShtolaUtils
{
    /// <summary>
    /// 用于模拟Numpy.interp的1D线性插值类
    /// </summary>
    public class Interpolator
    {
        /// <summary>
        /// 用于模拟Numpy.interp的1D线性插值
        /// </summary>
        /// <param name="x">用于计算插值值的x坐标。</param>
        /// <param name="xp">X轴上的数据点。<br></br>
        /// 当周期为true时则必定要求为单调递增,反之XP将在标准化后进行内部排序(用不上period)</param>
        /// <param name="fp">Y轴上的数据点,和XP同长</param>
        /// <param name="left">FP的左极值点</param>
        /// <param name="right">FP的右极值点</param>
        /// <returns>插值后的1D Array</returns>
        /// <exception cref="ArgumentException"></exception>
        public static double[] Interp(double[] x, double[] xp, double[] fp, double left = double.NaN, double right = double.NaN)
        {
            // 参数校验
            if (xp.Length != fp.Length)
                throw new ArgumentException("xp和fp长度必须一致");
            if (x.Length == 0)
                return new double[0];

            // 处理边界默认值
            if (double.IsNaN(left)) left = fp[0];
            if (double.IsNaN(right)) right = fp[^1]; // 使用 ^1 表示最后一个元素

            // 缓存边界值
            double minXP = xp[0];
            double maxXP = xp[^1];

            double[] result = new double[x.Length];
            int xpIndex = 0;

            for (int i = 0; i < x.Length; i++)
            {
                double currentX = x[i];

                // 处理左边界
                if (currentX <= minXP)
                {
                    result[i] = left;
                    continue;
                }

                // 处理右边界
                if (currentX >= maxXP)
                {
                    result[i] = right;
                    continue;
                }

                // 找到当前 x 在 xp 中的位置
                while (xpIndex < xp.Length - 1 && xp[xpIndex + 1] < currentX)
                {
                    xpIndex++;
                }

                // 计算线性插值
                double x0 = xp[xpIndex];
                double x1 = xp[xpIndex + 1];
                double y0 = fp[xpIndex];
                double y1 = fp[xpIndex + 1];

                // 提前计算斜率
                double slope = (y1 - y0) / (x1 - x0);
                result[i] = y0 + slope * (currentX - x0);
            }

            return result;
        }
    }
}

Not testing so much with performance,but i got same result as original numpy implementation

@henon
Copy link
Contributor

henon commented Feb 25, 2025

Ok, I see. Of course numpy will be faster if the arrays are really big. If they are small your c# code may be faster than Numpy because there is an overhead of calling into python. Anyway, I'll put this on my todo list and let you know when it's done.

@ElinLiu0
Copy link
Author

Ok, I see. Of course numpy will be faster if the arrays are really big. If they are small your c# code may be faster than Numpy because there is an overhead of calling into python. Anyway, I'll put this on my todo list and let you know when it's done.

Thanks a lot buddy,hope everything in progress and peachy

@ElinLiu0
Copy link
Author

Ok, I see. Of course numpy will be faster if the arrays are really big. If they are small your c# code may be faster than Numpy because there is an overhead of calling into python. Anyway, I'll put this on my todo list and let you know when it's done.

Hi bud,is that everything going as progressed or not?Is that feature published?

@henon
Copy link
Contributor

henon commented Mar 22, 2025

I got it working. The following testcase shows the usage:

        [TestMethod]
        public void interpTest()
        {
            // >>> xp = [1, 2, 3]
            // >>> fp = [3, 2, 0]
            // >>> np.interp(2.5, xp, fp)
            // 1.0
            // >>> np.interp([0, 1, 1.5, 2.72, 3.14], xp, fp)
            // array([ 3. ,  3. ,  2.5 ,  0.56,  0. ])
            // >>> UNDEF = -99.0
            // >>> np.interp(3.14, xp, fp, right=UNDEF)
            // -99.0
            // 

            var xp = new float[] { 1, 2, 3 };
            var fp = new float[] { 3, 2, 0 };
            Assert.AreEqual(1.0f, np.interp(2.5f, xp, fp));

            var given = np.interp(new float[] { 0, 1, 1.5f, 2.72f, 3.14f }, xp, fp);
            var expected =
                "array([3.        , 3.        , 2.5       , 0.55999994, 0.        ])";
            Assert.AreEqual(expected, given.repr);

            var UNDEF = -99.0f;
            Assert.AreEqual(-99.0f, np.interp(3.14f, xp, fp, right: UNDEF));

            // Interpolation with periodic x-coordinates:

            // >>> x = [-180, -170, -185, 185, -10, -5, 0, 365]
            // >>> xp = [190, -190, 350, -350]
            // >>> fp = [5, 10, 3, 4]
            // >>> np.interp(x, xp, fp, period=360)
            // array([7.5, 5., 8.75, 6.25, 3., 3.25, 3.5, 3.75])
            // 

            //var  x = [-180, -170, -185, 185, -10, -5, 0, 365];
            var x = new float[] { -180, -170, -185, 185, -10, -5, 0, 365 };
            xp = new float[] { 190, -190, 350, -350 };
            fp = new float[] { 5, 10, 3, 4 };
            given = np.interp(x, xp, fp, period: 360);
            expected =
               "array([7.5 , 5.  , 8.75, 6.25, 3.  , 3.25, 3.5 , 3.75])";
            Assert.AreEqual(expected, given.repr);

            // Complex interpolation:

            // >>> x = [1.5, 4.0]
            // >>> xp = [2,3,5]
            // >>> fp = [1.0j, 0, 2+3j]
            // >>> np.interp(x, xp, fp)
            // array([ 0.+1.j ,  1.+1.5j])

            x = new float[] { 1.5f, 4.0f };
            xp = new float[] { 2, 3, 5 };
            var fp2 = new [] { new Complex(0, 1), new Complex(0, 0), new Complex(2, 3) };
            given = np.interp(x, xp, fp2);
            expected =
               "array([0.+1.j , 1.+1.5j])";
            Assert.AreEqual(expected, given.repr);
        }

@henon
Copy link
Contributor

henon commented Mar 22, 2025

Released to nuget as as Numpy v3.11.1.35 (1f35173)
https://www.nuget.org/packages/Numpy/3.11.1.35

@ElinLiu0
Copy link
Author

Released to nuget as as Numpy v3.11.1.35 (1f35173)
https://www.nuget.org/packages/Numpy/3.11.1.35

Nice work,Since it's 1:00 AM in China right now,I will bring your reply when I wake up and fire up my workstation,good night: )

@ElinLiu0
Copy link
Author

Hi.I'm back here.

I've met a new problem with new version of Numpy.NET is that:when i running up the program,it will throw an warning message: Could not find platform dependent libraries <exec_prefix>

And then,when i call a numpy array in program,it may cause: PythonEngine is not initialized

@ElinLiu0
Copy link
Author

It won't happend on 3.10.1.30 release

@henon
Copy link
Contributor

henon commented Mar 24, 2025

I am pretty sure that you are doing something wrong. I updated the MatmulExample in the Numpy.NET source code to use the latest numpy library and ran it and it works just fine:

Output:

Efficient matrix multiplication with NumPy:
Could not find platform dependent libraries <exec_prefix>
execution time with NumPy: 70,4975ms

Result:
array([[ 1058680000,  1058699900,  1058719800, ...,  1066580300,
         1066600200,  1066620100],
       [-1644287296, -1644227396, -1644167496, ..., -1620506996,
        -1620447096, -1620387196],
       [  -52287296,   -52187396,   -52087496, ...,   -12626996,
          -12527096,   -12427196],
       ...,
       [ 1436277440,  1448177340,  1460077240, ...,  1865570444,
         1877470344,  1889370244],
       [-1266689856, -1254749956, -1242810056, ...,  -821516852,
         -809576952,  -797637052],
       [  325310144,   337290044,   349269944, ...,   786363148,
          798343048,   810322948]])
executing on bg thread
matmul on bg thread is done
Press key

Sure it also prints the Could not find platform dependent libraries <exec_prefix> And I don't know if that comes from PythonNet or from Python itself but it doesn't seem to be relevant.

I don't have time to debug your app so here is my advice. Use the MatmulExample as a base and add your code. Maybe that'll work for you.

@ElinLiu0
Copy link
Author

I am pretty sure that you are doing something wrong. I updated the MatmulExample in the Numpy.NET source code to use the latest numpy library and ran it and it works just fine:

Output:

Efficient matrix multiplication with NumPy:
Could not find platform dependent libraries <exec_prefix>
execution time with NumPy: 70,4975ms

Result:
array([[ 1058680000,  1058699900,  1058719800, ...,  1066580300,
         1066600200,  1066620100],
       [-1644287296, -1644227396, -1644167496, ..., -1620506996,
        -1620447096, -1620387196],
       [  -52287296,   -52187396,   -52087496, ...,   -12626996,
          -12527096,   -12427196],
       ...,
       [ 1436277440,  1448177340,  1460077240, ...,  1865570444,
         1877470344,  1889370244],
       [-1266689856, -1254749956, -1242810056, ...,  -821516852,
         -809576952,  -797637052],
       [  325310144,   337290044,   349269944, ...,   786363148,
          798343048,   810322948]])
executing on bg thread
matmul on bg thread is done
Press key

Sure it also prints the Could not find platform dependent libraries <exec_prefix> And I don't know if that comes from PythonNet or from Python itself but it doesn't seem to be relevant.

I don't have time to debug your app so here is my advice. Use the MatmulExample as a base and add your code. Maybe that'll work for you.

Oh i see,My Anaconda base is Py3.10. Is that a related reason?

@henon
Copy link
Contributor

henon commented Mar 24, 2025

Oh i see,My Anaconda base is Py3.10. Is that a related reason?

Yes, that would explain it. I can backport the change onto a 3.10 version of numpy.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants