Search code examples
pythonnumpyscipyoffsetnumerical-integration

Integration offset with cumtrapz (python/scipy)


I'd like to be able to numerically differentiate and integrate arrays in Python. I am aware that there are functions for this in numpy and scipy. I am noticing an offset however, when integrating.

As an example, I start with an initial function, y=cos(x).

image, y = cos(x)

I then take the derivative using numpy.gradient. It works as expected (plots as -sin(x)):

image, dydx = d/dx(cos(x))

When I integrate the derivative with scipy.cumtrapz, I expect to get back the initial function. However, there is some offset. I realize that the integral of -sin(x) is cos(x)+constant, so is the constant not accounted for with cumtrapz numerical integration?

image, y = int(dydx)

My concern is, if you have some arbitrary signal, and did not know the initial/boundary conditions, will the +constant term be unaccounted for with cumtrapz? Is there a solution for this with cumtrapz?

The code I used is as follows:

import numpy as np
import matplotlib.pyplot as plt
from scipy import integrate

x = np.linspace(-2*np.pi, 2*np.pi,100)

y = np.cos(x) #starting function 
dydx = np.gradient(y, x) #derivative of function 
dydx_int = integrate.cumtrapz(dydx, x, initial = 0) #integral of derivative 

fig, ax  = plt.subplots()
ax.plot(x, y)
ax.plot(x, dydx)
ax.plot(x, dydx_int)
ax.legend(['y = cos(x)', 'dydx = d/dx(cos(x))', 'y = int(dydx)'])
ax.set_xlabel('x')
ax.set_ylabel('y')
plt.show()

Solution

  • cumtrapz(), cumsum() and similar do what they state they do: summing the input array cumulatively. If the summed array starts with 0 as with your input array (dydx), the first element at the summed array is also zero.
    To fix it in your code, you should add the offset to the cumulated sum: dydx_int = dydx_int + y[0]

    But for the general question about initial conditions of an integral:

    My concern is, if you have some arbitrary signal, and did not know the initial/boundary conditions, will the +constant term be unaccounted for with cumtrapz? Is there a solution for this with cumtrapz?

    Well, if you don't know the initial/boundry condition, cumtrapz won't know either... Your question doesn't quite make sense..