How to run sicpy.signal freqz in C# / ASP.NET Core?

Question:

I need to run Python source code (.py) with dependencies on numpy and scipy.signal in the ASP.NET Core context. I’ve found IronPython to be a suitable solution, but it doesn’t support these two dependencies (GitHub issue #355).

So, I decided to automatically generate C# code from the Python one and manually check all build errors. All looks promising, numpy seems to be supported by Numpy.NET, but my missing puzzle is the freqz method of scipy.signal.

Example of usage:

w, h = signal.freqz(b, a, worN=freq_hz, fs=fs_hz)

Questions on the freqz function:

  1. Is there any C# fork of the function?
  2. Is there any source code of the function, so I can generate C# code from it?
  3. I was wondering if I can use MATLAB freqz function. Are these two functions equivalent? Is it possible to run that MATLAB function in the C# context?
Asked By: Dariusz Woźniak

||

Answers:

Basically, solution was to rewrite freqz function (I didn’t need to rewrite freqz completely, just part of the logic though) to C# along its dependent code (using Numpy):

public static (NDarray w, NDarray h) freqz(NDarray b,
                                           NDarray a,
                                           NDarray? worN,
                                           float fs = (float)Math.PI * 2)
{
    using var b_ = np.atleast_1d(b);
    using var a_ = np.atleast_1d(a);

    NDarray w = np.atleast_1d(worN);

    w = 2 * np.pi * w / fs;

    using var i = np.array(new Complex[] { new(real: 0, imaginary: -1) });
    var zm1 = (i * w).exp();

    var nppPolyval_b = npp_polyval(zm1, b_);
    var nppPolyval_a = npp_polyval(zm1, a_);
    NDarray h = nppPolyval_b / nppPolyval_a;

    w = w * fs / (2 * np.pi);

    return (w, h);
}

private static NDarray npp_polyval(NDarray x, NDarray c)
{
    using var c_ = np.array(c, ndmin: 1, copy: false);

    var c0 = c_[":, -1"] + x * 0;

    for (int i = 2; i <= c_.size; i++)
    {
        c0 = c_[$":, -{i}"] + (c0 * x);
    }
    return c0;
}
Answered By: Dariusz Woźniak