python - Efficiently recalculating the gradient of a numpy array with unknown dimensionality -
i have n-dimensional numpy array s
. every iteration, 1 value in array change.
i have second array, g
stores gradient of s
, calculated numpy's gradient()
function. currently, code unnecessarily recalculates of g
every time update s
, unnecessary, 1 value in s
has changed, , should have recalculate 1+d*2
values in g
, d
number of dimensions in s
.
this easier problem solve if knew dimensionality of arrays, solutions have come in absence of knowledge have been quite inefficient (not substantially better recalculating of g
).
is there efficient way recalculate necessary values in g
?
edit: adding attempt, requested
the function returns vector indicating gradient of s
@ coords
in each dimension. calculates without calculating gradient of s
@ every point, problem not seem efficient.
it looks similar in ways answers posted, maybe there quite inefficient it?
the idea following: iterate through each dimension, creating slice vector in dimension. each of these slices, calculate gradient , place appropriate value gradient correct place in returned vector grad
.
the use of min()
, max()
deal boundary conditions.
def getsgradat(self,coords) : """returns gradient of s @ position specified vector argument 'coords'. self.ndim : number of dimensions of s self.nbins : width of s (same in every dim) self.s : s """ grad = zeros(self.ndim) d in xrange(self.ndim) : # create slice through s has size > 1 in current # dimension, d. slices = list(coords) slices[d] = slice(max(0,coords[d]-1),min(self.nbins,coords[d]+2)) # take middle value gradient vector grad[d] = gradient(self.s[sl])[1] return grad
the problem doesn't run quickly. in fact, taking gradient of whole array s
seems run faster (for nbins = 25
, ndim = 4
).
edited again, add final solution
here ended using. function updates s
, changing value @ x
amount change
. updates g
using variation on technique proposed jaime.
def changesfield(self,x,change) : # change s self.s[x] += change # update g (gradient field) slices = tuple(slice(none if j-2 <= 0 else j-2, j+3, 1) j in x) newgrads = gradient(self.s[slices]) in arange(self.ndim) : self.g[i][slices] = newgrads[i]
your question open answer: idea post inefficient code, potential answerers can better you. anyway, lets know coordinates of point has changed, , store in tuple named coords
. first, lets construct tuple of slices encompassing point:
slices = tuple(slice(none if j-1 <= 0 else j-1, j+2, 1) j in coords)
you may want extend limits j-2
, j+3
gradient calculated using central differences whenever possible, slower.
you can update array doing like:
g[slices] = np.gradient(n[slices])
Comments
Post a Comment