Reputation: 3191
The following procedure results in values which do not always match the assigned ones:
from scipy.interpolate import splprep, splev, splrep
import numpy as np
pos2indx = lambda vec: vec.round().astype(np.int64)
t = np.linspace(1,3,150)
x = 150+100*np.sin(t) + 5*np.random.randn(len(t))
y = 150+100*np.cos(t) + 5*np.random.randn(len(t))
z = 150+100*np.cos(t)*np.sin(t) + 5*np.random.randn(len(t))
vector_field = np.zeros((x.max()+10,y.max()+10,z.max()+10,3), dtype=np.float64)
out = splprep([x,y,z],u=t,k=3, full_output=1, quiet=1)
tck, t = out[0]
v = np.transpose(splev(t,tck, der=1))
i,j,k = pos2indx(x),pos2indx(y),pos2indx(z)
vector_field[i,j,k,:] += v
print np.sum(np.abs(vector_field[i,j,k,:]-v))
I expected this procedure to always print zero. However, sometimes it does not! When the output is non-zero, it is of several thousands.
I am not sure whether I am doing something wrong or whether there's some bug here.
I reported this as a scipy issue as well.
Pauli Virtanen: "The bug is in your code: the i,j,k vectors can contain a given coordinate pair twice." ( https://github.com/scipy/scipy/issues/2581 )
jorgeca posted a similar answer below.
Thanks!
Upvotes: 2
Views: 207
Reputation: 5522
To summarize your problem, adding v
to an array of zeros and then substracting v
doesn't always yield an array of zeros:
vector_field = np.zeros((x.max()+10,y.max()+10,z.max()+10,3), dtype=np.float64)
vector_field[i,j,k,:] += v
print np.sum(np.abs(vector_field[i,j,k,:]-v)) # sometimes not 0!!
That can't be right!
In fact, the indices i
, j
and k
are numpy arrays, and so it's using fancy indexing. What should happen when a triplet of indices is repeated? That is, when the i[m] == i[n]
, j[m] == j[n]
and k[m] == k[n]
for some m, n. It turns out that by an implementation detail (that can change any time) only the last triplet (in C order) of indices will get assigned, and in the end vector_field[i,j,k,:]
doesn't really contain v
.
Upvotes: 2
Reputation: 58915
The problem seems to be caused by round error.
I did a comparison running your code 1000
times using dtypes: float16
, float32
, float64
and float96
; in vector_field
and counted the number of times it gives a non zero answer:
float16: 1000
float32: 1000
float64: 142
float96: 115
Upvotes: 1