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

Popular posts from this blog

html5 - What is breaking my page when printing? -

html - Unable to style the color of bullets in a list -

c# - must be a non-abstract type with a public parameterless constructor in redis -