# Equivalent of numpy.gradient in Julia

**URL:** <https://discourse.julialang.org/t/equivalent-of-numpy-gradient-in-julia/93172>\
**Category:** General Usage\
**Tags:** question, package\
**Created:** [January 18, 2023, 5:12pm UTC](https://discourse.julialang.org/t/equivalent-of-numpy-gradient-in-julia/93172 "2023-01-18T17:12:37Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![fdekerme](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fdekerme/32/43574_2.png) [@fdekerme](https://discourse.julialang.org/u/fdekerme)\
**Post date:** [January 18, 2023, 5:12pm UTC](https://discourse.julialang.org/t/equivalent-of-numpy-gradient-in-julia/93172/1 "2023-01-18T17:12:37Z")

</div>

Hello, 😁  
I need to calculate the gradient of a 3 dimensional matrix. Is there today in 2023 an equivalent of numpy.gradient in Julia?([numpy.gradient — NumPy v1.24 Manual](https://numpy.org/doc/stable/reference/generated/numpy.gradient.html))  
This question had already been asked, but the answer was not really satisfactory I think.

[Differentiation without explicit function (np.gradient) - New to Julia - Julia Programming Language (julialang.org)](https://discourse.julialang.org/t/differentiation-without-explicit-function-np-gradient/57784)

[Is there a central difference/gradient function somewhere? - General Usage - Julia Programming Language (julialang.org)](https://discourse.julialang.org/t/is-there-a-central-difference-gradient-function-somewhere/19454/2)

Thanks for your answer !  
fdekerm

---

<div class="post-metadata">

**Author:** ![ufechner7](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ufechner7/32/51363_2.png) [@ufechner7](https://discourse.julialang.org/u/ufechner7)\
**Post date:** [January 18, 2023, 5:19pm UTC](https://discourse.julialang.org/t/equivalent-of-numpy-gradient-in-julia/93172/2 "2023-01-18T17:19:34Z")

</div>

What are you missing in the answers given before?

---

<div class="post-metadata">

**Author:** ![fdekerme](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fdekerme/32/43574_2.png) [@fdekerme](https://discourse.julialang.org/u/fdekerme)\
**Post date:** [January 19, 2023, 9:26am UTC](https://discourse.julialang.org/t/equivalent-of-numpy-gradient-in-julia/93172/3 "2023-01-19T09:26:45Z")

</div>

Unless I missed something, I find that all the proposed solutions are quite complex and “artisanal” for something as simple as this, and which is done in one line with numpy. Especially since there was a time when there was a “gradient()” function directly in Base.

> <https://github.com/JuliaLang/julia/issues/16113>
>
> \`gradient(1:10)\` doesn't work because it dispatches to a method that only takes …\`Array\` arguments.
> 
> Also, \`gradient\` doesn't support multi-dimensional arrays, whereas in Matlab and NumPy it returns an N-tuple of the gradients along different directions.
> 
> cc: @andreasnoack, who looked at these functions in #5321.

---

<div class="post-metadata">

**Author:** ![ufechner7](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ufechner7/32/51363_2.png) [@ufechner7](https://discourse.julialang.org/u/ufechner7)\
**Post date:** [January 19, 2023, 9:39am UTC](https://discourse.julialang.org/t/equivalent-of-numpy-gradient-in-julia/93172/4 "2023-01-19T09:39:40Z")

</div>

OK, if I understand you correctly you would like to have a simple gradient() utility function that works on any number of dimensions, and you do not know in which package it should be placed, correct?

---

<div class="post-metadata">

**Author:** ![fdekerme](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fdekerme/32/43574_2.png) [@fdekerme](https://discourse.julialang.org/u/fdekerme)\
**Post date:** [January 19, 2023, 9:48am UTC](https://discourse.julialang.org/t/equivalent-of-numpy-gradient-in-julia/93172/5 "2023-01-19T09:48:19Z")

</div>

Yes, exactly!

---

<div class="post-metadata">

**Author:** ![ufechner7](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ufechner7/32/51363_2.png) [@ufechner7](https://discourse.julialang.org/u/ufechner7)\
**Post date:** [January 19, 2023, 10:25am UTC](https://discourse.julialang.org/t/equivalent-of-numpy-gradient-in-julia/93172/6 "2023-01-19T10:25:41Z")

</div>

I did not find any related package on [JuliaHub](https://juliahub.com/ui/Packages) .

Perhaps it would be worth to create a new package with such a function? Any comments?

---

<div class="post-metadata">

**Author:** ![Mattriks](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mattriks/32/351_2.png) [@Mattriks](https://discourse.julialang.org/u/Mattriks)\
**Post date:** [January 22, 2023, 10:29pm UTC](https://discourse.julialang.org/t/equivalent-of-numpy-gradient-in-julia/93172/7 "2023-01-22T22:29:04Z")

</div>

I added a `gradient` function to CoupledFields.jl (`]add CoupledFields#master` to try, see [Example 3 in the docs](https://mattriks.github.io/CoupledFields.jl/dev/man/Example3/#Example-3)). It uses a different method than `numpy.gradient`, but has the advantage of working for regular grids or irregular gridpoints. Let me know if it works for your case!

---

<div class="post-metadata">

**Author:** ![andrewkhardy](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/andrewkhardy/32/27311_2.png) [@andrewkhardy](https://discourse.julialang.org/u/andrewkhardy)\
**Post date:** [January 24, 2023, 5:45pm UTC](https://discourse.julialang.org/t/equivalent-of-numpy-gradient-in-julia/93172/8 "2023-01-24T17:45:54Z")

</div>

@Mattriks I’m confused by your syntax.

If I try `using CoupledFields: ndgrid`, I get the error

> ERROR: UndefVarError: ndgrid not defined

I also get errors for `i = range(-2, 2, 6)`. How do I run your example?

---

<div class="post-metadata">

**Author:** ![fedoroff](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fedoroff/32/53209_2.png) [@fedoroff](https://discourse.julialang.org/u/fedoroff)\
**Post date:** [January 24, 2023, 6:17pm UTC](https://discourse.julialang.org/t/equivalent-of-numpy-gradient-in-julia/93172/9 "2023-01-24T18:17:04Z")

</div>

Can you please tell which exactly method do you use for gradient calculation in case of irregular grid points.

---

<div class="post-metadata">

**Author:** ![Mattriks](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mattriks/32/351_2.png) [@Mattriks](https://discourse.julialang.org/u/Mattriks)\
**Post date:** [January 24, 2023, 7:22pm UTC](https://discourse.julialang.org/t/equivalent-of-numpy-gradient-in-julia/93172/10 "2023-01-24T19:22:00Z")

</div>

For now, the new function is available on master branch:

```julia
]add CoupledFields#master

```

---

<div class="post-metadata">

**Author:** ![Mattriks](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mattriks/32/351_2.png) [@Mattriks](https://discourse.julialang.org/u/Mattriks)\
**Post date:** [January 24, 2023, 7:25pm UTC](https://discourse.julialang.org/t/equivalent-of-numpy-gradient-in-julia/93172/11 "2023-01-24T19:25:33Z")

</div>

I’m going to add a “Theory” page to the CoupledFields documentation, but for now there is a brief explanation here: [Smooth delta functions to compute Jacobian and Hessian from samples - #10 by Mattriks](https://discourse.julialang.org/t/smooth-delta-functions-to-compute-jacobian-and-hessian-from-samples/45282/10)

---

<div class="post-metadata">

**Author:** ![tim.holy](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tim.holy/32/52_2.png) [@tim.holy](https://discourse.julialang.org/u/tim.holy)\
**Post date:** [January 24, 2023, 7:49pm UTC](https://discourse.julialang.org/t/equivalent-of-numpy-gradient-in-julia/93172/12 "2023-01-24T19:49:40Z")

</div>

The fact that this is hard to find may be because in Julia you often don’t actually need to store the gradient as an array (or tuple-of-arrays), instead you compute it pointwise on the fly as an input to whatever other computation you’re actually doing. In other words, the gradient does not need to be an “endpoint” of something in Julia.

That said, there are a couple that haven’t been mentioned:

- [Reference · ImageBase](https://juliaimages.org/ImageBase.jl/stable/reference/#Discrete-gradient-operator). This doesn’t use second-order differencing but it has the other characteristics.
- [https://juliaimages.org/ImageFiltering.jl/stable/:](https://juliaimages.org/ImageFiltering.jl/stable/:) `imgradients(A, KernelFactors.sobel)` should basically give you what you want, but know that `sobel` does a bit of averaging over nearest-neighbors and will not be exactly the same as the two-point gradient you’re currently using.

---

<div class="post-metadata">

**Author:** ![Mattriks](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mattriks/32/351_2.png) [@Mattriks](https://discourse.julialang.org/u/Mattriks)\
**Post date:** [January 24, 2023, 8:01pm UTC](https://discourse.julialang.org/t/equivalent-of-numpy-gradient-in-julia/93172/13 "2023-01-24T20:01:10Z")

</div>

The OP mentions “the gradient of a 3d matrix” (which I assume means 3d positions, and a 1d variable at those positions), can imgradients be used?

---

<div class="post-metadata">

**Author:** ![stillyslalom](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stillyslalom/32/45687_2.png) [@stillyslalom](https://discourse.julialang.org/u/stillyslalom)\
**Post date:** [January 24, 2023, 8:03pm UTC](https://discourse.julialang.org/t/equivalent-of-numpy-gradient-in-julia/93172/14 "2023-01-24T20:03:42Z")

</div>

Interpolations.jl works for this, too, although with a bit more overhead than in-place calculation:

```julia
julia> using Interpolations

julia> v = rand(3, 3, 3);

julia> itp = linear_interpolation(axes(v), v);

julia> [Interpolations.gradient(itp, idx...) for idx in knots(itp)]
3×3×3 Array{StaticArraysCore.SVector{3, Float64}, 3}:
[:, :, 1] =
 [0.0217651, 0.081234, 0.245227] [0.422528, 0.50527, 0.237876] [-0.336426, 0.50527, -0.153063]
 [-0.140606, 0.481997, 0.47315] [-0.205345, -0.253683, -0.562774] [-0.184544, -0.253683, -0.330334]
 [-0.140606, 0.417258, 0.815596] [-0.205345, -0.232882, -0.0649707] [-0.184544, -0.232882, 0.0365438]

[:, :, 2] =
 [0.249688, 0.0738826, 0.347969] [-0.378122, 0.114332, -0.0942331] [-0.513697, 0.114332, -0.253928]
 [0.201841, -0.553927, 0.189845] [0.292458, -0.0212431, 0.726295] [0.182334, -0.0212431, 0.368639]
 [0.201841, -0.463309, 0.0285594] [0.292458, -0.131368, 0.152346] [0.182334, -0.131368, 0.292275]

[:, :, 3] =
 [0.0915639, -0.368319, 0.347969] [0.442407, -0.0453636, -0.0942331] [0.10887, -0.0453636, -0.253928]
 [0.0405551, -0.0174767, 0.189845] [-0.281491, -0.3789, 0.726295] [0.105971, -0.3789, 0.368639]
 [0.0405551, -0.339523, 0.0285594] [-0.281491, 0.00856203, 0.152346] [0.105971, 0.00856203, 0.292275]

```

---

<div class="post-metadata">

**Author:** ![tim.holy](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tim.holy/32/52_2.png) [@tim.holy](https://discourse.julialang.org/u/tim.holy)\
**Post date:** [January 24, 2023, 8:06pm UTC](https://discourse.julialang.org/t/equivalent-of-numpy-gradient-in-julia/93172/15 "2023-01-24T20:06:15Z")

</div>

Yes, it’s arbitrary-dimensional.

---

<div class="post-metadata">

**Author:** ![Mattriks](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mattriks/32/351_2.png) [@Mattriks](https://discourse.julialang.org/u/Mattriks)\
**Post date:** [January 24, 2023, 8:15pm UTC](https://discourse.julialang.org/t/equivalent-of-numpy-gradient-in-julia/93172/16 "2023-01-24T20:15:47Z")

</div>

What about 3d positions and a 2d variable? 😀

---

<div class="post-metadata">

**Author:** ![tim.holy](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tim.holy/32/52_2.png) [@tim.holy](https://discourse.julialang.org/u/tim.holy)\
**Post date:** [January 24, 2023, 8:29pm UTC](https://discourse.julialang.org/t/equivalent-of-numpy-gradient-in-julia/93172/17 "2023-01-24T20:29:41Z")

</div>

Not fully sure I know what you mean, is it this?

```julia
julia> using StaticArrays, ImageFiltering

julia> A = [SVector(rand(), rand()) for i = 1:3, j = 1:3, k = 1:3];

julia> g1, g2, g3 = imgradients(A, KernelFactors.sobel);

julia> g1
3×3×3 Array{SVector{2, Float64}, 3}:
[:, :, 1] =
 [0.0762768, 0.122968] [0.00718473, 0.081613] [-0.0166742, -0.0798793]
 [0.127677, 0.16464] [0.0277456, 0.130215] [-0.154041, 0.105112]
 [0.0514005, 0.0416719] [0.0205609, 0.0486023] [-0.137366, 0.184991]

[:, :, 2] =
 [0.0474921, 0.155314] [0.0466046, 0.120711] [-0.0332256, 0.0171544]
 [0.137826, 0.202603] [0.113671, 0.134971] [0.000161656, 0.0273804]
 [0.0903337, 0.0472892] [0.0670666, 0.0142602] [0.0333872, 0.010226]

[:, :, 3] =
 [0.00795333, -0.0351133] [0.066914, -0.0367565] [-0.0944003, -0.0250204]
 [0.0625429, 0.102988] [0.112584, 0.106004] [-0.0335448, -0.0150227]
 [0.0545896, 0.138101] [0.0456702, 0.14276] [0.0608555, 0.00999772]

```

It also works with `A = [rand(SMatrix{5,5}) for i = 1:3, j = 1:3, k = 1:3];`, if that’s what you mean by a 2d variable.

---

<div class="post-metadata">

**Author:** ![Mattriks](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mattriks/32/351_2.png) [@Mattriks](https://discourse.julialang.org/u/Mattriks)\
**Post date:** [January 25, 2023, 6:05am UTC](https://discourse.julialang.org/t/equivalent-of-numpy-gradient-in-julia/93172/18 "2023-01-25T06:05:55Z")

</div>

That looks right, I should do a comparison sometime.

---

<div class="post-metadata">

**Author:** ![tim.holy](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tim.holy/32/52_2.png) [@tim.holy](https://discourse.julialang.org/u/tim.holy)\
**Post date:** [January 25, 2023, 9:29am UTC](https://discourse.julialang.org/t/equivalent-of-numpy-gradient-in-julia/93172/19 "2023-01-25T09:29:03Z")

</div>

Keep in mind that you may see small numerical differences due to the fact that this notion of “gradient” comes from applying (in 2d) the following stencils:

```julia
julia> using ImageFiltering

julia> g1, g2 = Kernel.sobel();

julia> g1
3×3 OffsetArray(::Matrix{Float64}, -1:1, -1:1) with eltype Float64 with indices -1:1×-1:1:
 -0.125 -0.25 -0.125
  0.0 0.0 0.0
  0.125 0.25 0.125

julia> g2
3×3 OffsetArray(::Matrix{Float64}, -1:1, -1:1) with eltype Float64 with indices -1:1×-1:1:
 -0.125 0.0 0.125
 -0.25 0.0 0.25
 -0.125 0.0 0.125

```

You should be able to replicate the `numpy` notion exactly with

```julia
g1, g2 = KernelFactors.sobel((true, false), 1), KernelFactors.sobel((false, true), 2)

```

which is just a (too complicated?) way of `imfilter`ing with `centered(SVector(-0.5, 0, 0.5))` and `centered(SVector(-0.5, 0, 0.5)')` (which doesn’t quite work).

---

<div class="post-metadata">

**Author:** ![stillyslalom](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stillyslalom/32/45687_2.png) [@stillyslalom](https://discourse.julialang.org/u/stillyslalom)\
**Post date:** [January 25, 2023, 6:02pm UTC](https://discourse.julialang.org/t/equivalent-of-numpy-gradient-in-julia/93172/20 "2023-01-25T18:02:07Z")

</div>

It’d be great to have these standard finite difference kernels in ImageFiltering or some extension package, and/or to spin out the kernel/window functions into a separate package (KernelOperators.jl, maybe under the JuliaArrays org?). At the moment, I don’t think there’s a package for textbook vector calculus operators on gridded data, and I’ve ended up cobbling them together whenever they’re needed from Interpolations or ImageFiltering. For `curl` in particular, this requires wasteful allocation/computation of the diagonal part of the Jacobian.

[Next page](https://discourse.julialang.org/t/equivalent-of-numpy-gradient-in-julia/93172.md?page=2)
