arrayfire / arrayfire-python

Python bindings for ArrayFire: A general purpose GPU library.

Home Page:https://arrayfire.com

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Doubt regarding use of interpolation function

shyams2 opened this issue · comments

I'm a bit confused about the use of the interpolation function arrayfire.signal.approx1(signal, pos0). The documentation states that it accepts 2 arguments: the signal value, and the interpolation points. How can I specify the array which defines the points where the signal has been defined? I'll take an example using the numpy function np.interp:

x = np.linspace(0, 2*np.pi, 100)
y = np.sin(x)

x_interp = np.linspace(0, 2*np.pi, 50)
y_interp = np.interp(x_interp, x, y) # generates the values at the interpolated points

How would I approach this using the arrayfire functions?

Hmm there are two issues:

  1. no direct equivalent of linspace in arrayfire.
  2. interp in arrayfire is uniform only so it assumes the input x is always 1 to N.

But you can still get the same results you are seeing. You'll just need to scale up y to meet this new co-ordinate system.

interp in arrayfire is uniform only so it assumes the input x is always 1 to N.

Alright. That's what I wanted to know. But I'm still not able to understand how I would get the same results. I don't think I've clearly understood how the coordinate system needs to be scaled. This is what I tried:

x_np = np.linspace(0, 2*np.pi, 100)
y_np = np.sin(x_np)
x_np = x_np/(x_np[1]) + 1 # Scaling from 1 - 100

x_af = af.Array(x_np.tolist())
y_af = af.Array(y_np.tolist())

x_interp = np.linspace(0, 2*np.pi, 50)
x_scale  = 2 * ((x_interpx_interp[1])+1) # Fitting x_scale between 1-100
x_scale  = af.Array(x_scale.tolist())

y_interpolate = af.signal.approx1( y_af, x_scale)

I don't seem to be getting the result, though. How should I have done this?

import numpy as np
import arrayfire as af

x = np.linspace(0, 2 * np.pi, 20)
y = np.sin(x)
step_size = (x[1] - x[0])

x_interp = np.linspace(0, 2 * np.pi, 10)
y_interp = np.interp(x_interp, x, y)

y_af  = af.to_array(y)
x_interp_af = af.to_array(x_interp / step_size)
y_interp_af = af.approx1(y_af, x_interp_af)

print(y_interp)
print(y_interp_af)

@ShyamSS-95 let me know if that makes sense. BTW you don't need to convert to list to convert numpy to arrayfire. I reduced the sizes so I can see more clearly if the results are correct.

I must say I made some mistakes in my older comment as I was in a hurry. Sorry about that. The x values are assumed to be between 0 and N-1. Your code seems to follow the instructions I made in my older comment so there was no mistake on your end. I am sorry if this delayed things.

@pavanky Ah OK! It's clear to me now. Thanks

I must say I made some mistakes in my older comment as I was in a hurry. Sorry about that. The x values are assumed to be between 0 and N-1. Your code seems to follow the instructions I made in my older comment so there was no mistake on your end. I am sorry if this delayed things.

Not a problem at all.

Also, I wanted to know if it's alright for me to run the af.approx1 function inside a gfor loop?

@ShyamSS-95 you usually don't need GFOR. Can you tell me what you have in mind ?

@pavanky I'm trying to obtain the interpolated values for a field function field interpolated at some points x_interp. Both field and x_inter are 2D arrays, where the interpolation needs to be carried out row-wise.
Currently, I'm using something like this:

f_interp = af.data.constant(0, Ny, Nx) # Initializing
for i in range(Ny):
  f_interp[i, :] = af.approx1(field[i, :], x_interp[i, :])

Wouldn't using af.ParallelRange help in speeding this up?

@ShyamSS-95

ArrayFire works on each column. If you transformed the data to be along each column, you can simply do the following:

f_interp = af.approx1(field, x_interp)

This performs multiple 1D interpolations along each column.

Ah OK. This would work well for my purpose. Thank You