2-dimensional interpolation - c++

I want to find a value of z at y = 12 and x = 3.5, given the below example data. How can I do this in C++?
y = 10
x = [1,2, 3,4, 5,6]
z = [2.3, 3.4, 5.6, 7.8, 9.6, 11.2]
y = 20
x = [1,2, 3,4, 5,6]
z = [4.3, 5.4, 7.6, 9.8, 11.6, 13.2]
y = 30
x = [1,2, 3,4, 5,6]
z = [6.3, 7.4, 8.6, 10.8, 13.6, 15.2]
My current Python code:
import scipy
import math
import numpy
from scipy import interpolate
x = [1, 2, 3, 4, 5, 6]
y = [10, 20, 30]
Y = numpy.array([[i]*len(x) for i in y])
X = numpy.array([x for i in y])
Z = numpy.array([[2.3, 3.4, 5.6, 7.8, 9.6, 11.2],
[4.3, 5.4, 7.6, 9.8, 11.6, 13.2],
[6.3, 7.4, 8.6, 10.8, 13.6, 15.2]])
tck = interpolate.bisplrep(X, Y, Z)
print interpolate.bisplev(3.5, 15, tck)

Just do the interpolation twice. First interpolate with Y to select the two Z tables. Then interpolate with X to pick the Z value.

I would use Akima's Spline, which is very well-tested, very fast, and produces extremely good results.
Unfortunately, it's in Fortran-66 (and messy at that), so you'll need to either translate it to C or a more modern variant of Fortran. I've gotten some help in getting it all to work, so I'd suggest reading through my threads on Usenet.

Related

How to create an array using for loop while by keeping range fixed in python

newarray = [x + 0.5 for x in range(1, 10)]
this code will give me following result:
newarray
[1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5, 8.5, 9.5]
Instead of adding 0.5 with x I want to increase my x by 0.5 for each 1 increment of x. The output suppose to be
newarray=[0.5,1,1.5,2,2.5......5.5].
Keep in mind that my range must be fix in 1 to 10. What can be better approach to make that?
[0.5 * x for x in range(1, 12)]
Will do the thing, I'm afraid generating that array with range(1, 10) is impossible

select a specific range from a numpy 2d array to plot values

for example with a numpy array like the following,
a=([1,2,3,4,5], [100,200,300,400,500]) and x=a[0] and y=a[1]
how can I plot xy where 2 < x < 4 ?
You could try masks on arrays: http://docs.scipy.org/doc/numpy/reference/routines.ma.html
Here's an example of what I mean:
import numpy as np
x = np.array([1,2,3,4,5])
y = np.array([100,200,300,400,500])
# b contains true when corresponding value of x is outside 2 < x < 4
b = np.ma.masked_outside(x, 2, 4).mask
# x2 originates from x, but values 2 < x < 4 are stripped (according to the boolean variables contained in b), the same is done with y2
x2 = x[~b]
y2 = y[~b]
print 'x2', x2
print 'y2', y2
When its only about plotting, you could just use
import matplotlib.pyplot as plt
plt.plot(x,y)
plt.axis((2,4,None,None))
plt.show()
>>> from numpy import array
>>> a=array(([1,2,3,4,5], [100,200,300,400,500]))
>>> a[:, (2 < a[0])*(a[0] < 4)]
array([[ 3],
[300]])
Since that just gives a single point, let's choose another range:
>>> a[:, (1.5 < a[0])*(a[0] < 4.5)]
array([[ 2, 3, 4],
[200, 300, 400]])
To explain, (1.5 < a[0])*(a[0] < 4.5) is a vector of true and false values. It is true whenever x is between 1.5 and 4.5. Numpy can use such boolean vectors to select just those values. We use that for the second axis.
For the first axis, if we had used 0 (as in a[0, (1.5 < a[0])*(a[0] < 4.5)]), we would have gotten just the x-values between 1.5 and 4.5. If we had used 1, we would have gotten just the y values that correspond to that x-range. If we want an array with both the x and y values, we can use : for the first axis which means "all".
If we want to plot those values:
b = a[:, (1.5 < a[0])*(a[0] < 4.5)]
import matplotlib.pyplot as plt
p = plt.plot(b[0], b[1])
plt.show()

Python - Plotting a raster image/contour plot with XY and Z points

I have a set of X and Y coordinates and each point has a different pixel value - the Z quantity. I would like to plot these values using a raster or contour plot.
I am having difficulty doing this because there is no mathematical relationship between the pixel value and the X and Y coordinates.
I have created an array for the range of x and y values and I have tried constructing a dictionary where I can look up the value of z using a concatenated x and y string. At the moment I am having an index issue and I am wondering if there is a better way of achieving this?
My code so far is:
import matplotlib.pyplot as plt
import numpy as np
XY_Zpoints = {'11':8,
'12':8,
'13':8,
'14':6,
'21':6,
'22':8,
'23':6,
'24':6,
'31':8,
'32':3,
'33':8,
'34':6,
'41':8,
'42':3,
'43':3,
'44':8,
}
x, y = np.meshgrid(np.linspace(1,4,4), np.linspace(1,4,4))
z = XY_Zpoints[str(x)+str(y)]
# Plot the grid
plt.imshow(z)
plt.spectral()
plt.show()
Thanks in advance for any help you can offer!
Instead of a dictionary, you can use a numpy array where the position of each pixel value coresponds to the x and y coordinates. For your example this array would look like:
z = np.array([[8, 8, 8, 6], [6, 8, 6, 6], [8, 3, 8, 6], [8, 3, 3, 8]])
To access the pixel value at x = 2 and y = 3, for example you can do this:
x = 2
y = 3
pixel = z[x-1][y - 1]
z can be displayed with:
imshow(z)

Mathematica- If statement not performing true/false

I have a notebook set up to run through an exhaustive search of numbers in an array used in an equation, if the equation equals a defined variable, then it returns the values of the variables in the equation. The only problem is, the If statement in the last For-loop never runs through the true/false/neither functions. The only way I've been able to get it to do anything is to use a generic Print[blah], of which it then proceeds to print absolutely every iteration through all the For-loops. Here is what I have so far-
AvTarget := -95
arr := {1, 1.1, 1.2, 1.3, 1.5, 1.6, 1.8, 2, 2.2, 2.4, 2.7, 3, 3.3,
3.6, 3.9, 4.3, 4.7, 5.1, 5.6, 6.2, 6.8, 7.5, 8.2, 9.1, 10}
trueArr := {}
falseArr := {}
For[i = 1, i <= Length[arr], i = i + 1,
For[j = 1, j <= Length[arr], j = j + 1,
For[k = 1, k <= Length[arr], k = k + 1,
If[Abs[
AvTarget - (arr[[i]] + arr[[k]] + (arr[[i]] + arr[[k]])/
arr[[j]])] < 1000, Append[trueArr, {i, j, k}],
Append[falseArr, 1], Append[falseArr, 0]]
]
]
]
Length[trueArr]
Length[falseArr]
I haven't dealt with loops in mathematica yet so I'm not sure what the issue is.
EDIT-
Ok so this code now works the way I need it to -
AvTarget = -95;
tol = 0.1;
arr := {1, 1.1, 1.2, 1.3, 1.5, 1.6, 1.8, 2, 2.2, 2.4, 2.7, 3, 3.3,
3.6, 3.9, 4.3, 4.7, 5.1, 5.6, 6.2, 6.8, 7.5, 8.2, 9.1, 10}
trueArr = {};
falseArr = {};
For[i = 1, i <= Length[arr], i++,
For[j = 1, j <= Length[arr], j++,
For[k = 1, k <= Length[arr], k++,
If[Abs[
AvTarget - (-(arr[[i]] + arr[[k]] + (arr[[i]]*arr[[k]])/
arr[[j]]))] <= tol,
trueArr = Append[trueArr, {arr[[i]], arr[[j]], arr[[k]]}],
Append[falseArr, 1], Append[falseArr, 0]]
]
]
]
Length[trueArr]
From there if Length > 0 I can just add an If to display the results. What would be the best way to have all the results within the tolerance printed in order of closest to AvTarget?
Loops are almost always the wrong way to go with Mathematica. I rewrote your original code to
avTarget = -95;
arr := {1, 1.1, 1.2, 1.3, 1.5, 1.6, 1.8, 2, 2.2, 2.4, 2.7, 3, 3.3,
3.6, 3.9, 4.3, 4.7, 5.1, 5.6, 6.2, 6.8, 7.5, 8.2, 9.1, 10};
triples = Tuples[arr, 3];
trueArr = Select[triples, Abs[avTarget - (#[[1]] + #[[3]] + (#[[1]] + #[[3]])/#[[2]]) <
1000] &];
falseArr = Complement[triples,trueArr];
I've been using Mathematica for about 20 years, I can't recall ever needing loops. Sure, sometimes it's easier to express an algorithm using loops than the functional alternatives that Mathematica provides but you should really kick away the crutches that they provide and walk the Mathematica way.
You should assign the return value of Append to the respective variable.
Append[trueArr, {i,j,k}] gives trueArr with {i,j,k} appended and then discards the result. You want trueArr = Append[trueArr, {i, j, k}].
Also, ":=" is the SetDelayed operator. You should be using "=".

Making a list of evenly spaced numbers in a certain range in python

What is a pythonic way of making list of arbitrary length containing evenly spaced numbers (not just whole integers) between given bounds? For instance:
my_func(0,5,10) # ( lower_bound , upper_bound , length )
# [ 0, 0.5, 1, 1.5, 2, 2.5, 3, 3.5, 4, 4.5 ]
Note the Range() function only deals with integers. And this:
def my_func(low,up,leng):
list = []
step = (up - low) / float(leng)
for i in range(leng):
list.append(low)
low = low + step
return list
seems too complicated. Any ideas?
Given numpy, you could use linspace:
Including the right endpoint (5):
In [46]: import numpy as np
In [47]: np.linspace(0,5,10)
Out[47]:
array([ 0. , 0.55555556, 1.11111111, 1.66666667, 2.22222222,
2.77777778, 3.33333333, 3.88888889, 4.44444444, 5. ])
Excluding the right endpoint:
In [48]: np.linspace(0,5,10,endpoint=False)
Out[48]: array([ 0. , 0.5, 1. , 1.5, 2. , 2.5, 3. , 3.5, 4. , 4.5])
You can use the following approach:
[lower + x*(upper-lower)/length for x in range(length)]
lower and/or upper must be assigned as floats for this approach to work.
Similar to unutbu's answer, you can use numpy's arange function, which is analog to Python's intrinsic function range. Notice that the end point is not included, as in range:
>>> import numpy as np
>>> a = np.arange(0,5, 0.5)
>>> a
array([ 0. , 0.5, 1. , 1.5, 2. , 2.5, 3. , 3.5, 4. , 4.5])
>>> a = np.arange(0,5, 0.5) # returns a numpy array
>>> a
array([ 0. , 0.5, 1. , 1.5, 2. , 2.5, 3. , 3.5, 4. , 4.5])
>>> a.tolist() # if you prefer it as a list
[0.0, 0.5, 1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5]
f = 0.5
a = 0
b = 9
d = [x * f for x in range(a, b)]
would be a way to do it.
Numpy's r_ convenience function can also create evenly spaced lists with syntax np.r_[start:stop:steps]. If steps is a real number (ending on j), then the end point is included, equivalent to np.linspace(start, stop, step, endpoint=1), otherwise not.
>>> np.r_[-1:1:6j, [0]*3, 5, 6]
array([-1. , -0.6, -0.2, 0.2, 0.6, 1.])
You can also directly concatente other arrays and also scalars:
>>> np.r_[-1:1:6j, [0]*3, 5, 6]
array([-1. , -0.6, -0.2, 0.2, 0.6, 1. , 0. , 0. , 0. , 5. , 6. ])
You can use the folowing code:
def float_range(initVal, itemCount, step):
for x in xrange(itemCount):
yield initVal
initVal += step
[x for x in float_range(1, 3, 0.1)]
Similar to Howard's answer but a bit more efficient:
def my_func(low, up, leng):
step = ((up-low) * 1.0 / leng)
return [low+i*step for i in xrange(leng)]