API Reference

Public Interface

neffint.fourier_integral_fixed_sampling(times: _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | bool | int | float | complex | str | bytes | _NestedSequence[bool | int | float | complex | str | bytes], frequencies: _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | bool | int | float | complex | str | bytes | _NestedSequence[bool | int | float | complex | str | bytes], func_values: _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | bool | int | float | complex | str | bytes | _NestedSequence[bool | int | float | complex | str | bytes], pos_inf_correction_term: bool, neg_inf_correction_term: bool, interpolation: str) ndarray

Calculates the fourier integral of a function for the time values given as input:

integral from fmin to fmax of : exp(2*pi*j*f*t)*func(f)*df,

where t is the time, fmin is the first frequency in the input frequencies, fmax is either the highest frequency or (positive) infinity, depending on inf_correction_term, and func(f) is the input function of frequency. The function is given as an array of outputs corresponding to the array of frequencies given.

A Filon type algorithm using a either a piecewise cubic Hermite interpolating polynomial ([PCHIP]) or a piecewise linear polynomial, depending on the interpolation argument. Optionally, an asymptotic correction term can also be computed at each end. For details on implementation, see [N.Mounet-PhD].

Parameters:
  • times (ArrayLike) – Float or 1D array of floats of length M, the time(s) [s]* to compute the fourier integral for

  • frequencies (ArrayLike) – Float or 1D array of floats of length N, the frequencies [Hz]* the function to be transformed have been evaluated at

  • func_values (ArrayLike) – Complex or ND array of complex of shape (N, X1, X2, …), the outputs of the function to be transformed at the frequencies given as input

  • pos_inf_correction_term (bool) – True if an asymptotic correction term towards +infinity should be added, otherwise the integral is effectively truncated at the highest frequency

  • neg_inf_correction_term (bool) – True if an asymptotic correction term towards -infinity should be added, otherwise the integral is effectively truncated at the lowest (closest to -inf) frequency

  • interpolation (str) – String either equal to “pchip” or “linear”, to select the integration methods using PCHIP or piecewise linear interpolation, respectively.

Returns:

The fourier integral of the input function at the input times, given as an array of shape (M, X1, X2, …)

Return type:

np.ndarray

*Though the units s and Hz are used here, any coherent set of time and frequency units will work

neffint.fourier_integral_adaptive(times: _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | bool | int | float | complex | str | bytes | _NestedSequence[bool | int | float | complex | str | bytes], initial_frequencies: Sequence, func: Callable[[float], _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | bool | int | float | complex | str | bytes | _NestedSequence[bool | int | float | complex | str | bytes]], absolute_integral_tolerance: float, interpolation: str = 'pchip', step_towards_inf_factor: float = 2, bisection_mode_condition: Callable[[ndarray], ndarray] | None = None, interpolation_error_norm: Callable[[ndarray, ndarray], ndarray] | None = None, max_iterations: int | None = None) ndarray

Performs an adaptive algorithm to improve a frequency range and uses the improved frequency range to compute the Fourier integral of func

The algorithm finds new frequencies by creating a PCHIP interpolaion of func on the frequencies, comparing that interpolation with the true function value the midpoints of all frequency subintervals, and using Simpson’s rule to evaluate the integral of the difference between the interpolation and the true function. The midpoint of the subinterval with the largest interpolation error is then added to the frequencies array.

This repeats either until max_iterations iterations have been performed, or until the interpolation error integral has a smaller total value than absolute_integral_tolerance

To avoid many repeated calls to func, the outputs are cached, so that reevaluation at the same frequency only amounts to a dictionary lookup.

func should only give finite outputs for all frequencies between the extremes of the input frequencies.

The improved frequency range will never exceed the boundaries of the input.

+-inf can be included in the frequency range, but user discretion is advised, as depending on func and step_towards_inf_factor, adding frequencies towards inf can come at the cost of adding frequencies close to the most important features of func.

It should be noted that while the algorithm will run with as little as 2 initial frequencies, it is for the best results advised to use a frequency range that already captures the most essential features of func, and thus use the algorithm to improve this range.

The Fourier integral itself is the integral from fmin to fmax of : exp(2*pi*j*f*t)*func(f)*df,

where t is the time, fmin is the first frequency in the input frequencies, fmax is the highest frequency and func(f) is the input function of frequency.

It is computed using a Filon type algorithm using a piecewise cubic Hermite interpolating polynomial (pchip). For details on implementation, see [N.Mounet-PhD].

This function combines the functionality of neffint.improve_frequency_range and neffint.fourier_integral_fixed_sampling, and only for convenience. If the improved frequencies or the corresponding function values are needed, use the two functions separately.

Based on the algorithm outlined in section 1.6.3 in [N.Mounet-PhD].

Parameters:
  • times (ArrayLike) – Float or 1D array of floats, the time(s) [s]* to compute the fourier integral for

  • initial_frequencies (Sequence[float]) – A 1D array of floats containing the starting frequencies [Hz]* for the algorithm. Must contain at least 2 frequencies. Can contain +-np.inf.

  • func (Callable[[float], ArrayLike]) – The function to be Fourier integrated, a function of frequency [Hz] with a complex output. Does not need to be vectorized. Results will be cached to avoid repeat calls with the same input.

  • interpolation_error_norm (Optional[Callable[[np.ndarray, np.ndarray], np.ndarray]]) – A callable that takes in an array of func outputs (shape (N, X1, X2, …)) and interpolated approximations of the same values (also shape (N, X1, X2, …)) The primary axis (of length N) corresponds to the frequency. The callable should return a norm of the difference between the two inputs, collapsed into a 1D array along the frequency axis, i.e. the output should have the shape (N,). If None (the default) is given, the norm will be calculated using the absolute difference for 1D arrays, or the 2-norm for higher dimension arrays

  • absolute_integral_tolerance (float) – The tolerance for the (approximate) integrated interpolation error. When the error drops below this value, the algorithm terminates.

  • step_towards_inf_factor (float, optional) – When one of the ends of the frequency array is +-inf, the bisection of the corresponding interval is calculated by multiplying the (finite) neighboring frequency with this number. Defaults to 2

  • bisection_mode_condition (Optional[Callable[[np.ndarray], np.ndarray]], optional) – A function that takes in a frequency array [Hz]* and returns an array of bools of the same size, where True denotes that the interval following that frequency should be bisected linearly, and False geometrically. Can be set to None, in which case only geometric bisection is used. Defaults to None

  • max_iterations (Optional[int], optional) – The maximum amount of iterations to perform before the algorithm is terminated. If set to None, the algorithm will only terminate after the tolerance has been met. Defaults to None

Returns:

The fourier integral of func for the given input times

Return type:

np.ndarray

*Though the units s and Hz are used here, any coherent set of time and frequency units will work

neffint.improve_frequency_range(initial_frequencies: Sequence[float], func: Callable[[float], _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | bool | int | float | complex | str | bytes | _NestedSequence[bool | int | float | complex | str | bytes]], absolute_integral_tolerance: float, step_towards_inf_factor: float = 2, bisection_mode_condition: Callable[[ndarray], ndarray] | None = None, interpolation_error_norm: Callable[[ndarray, ndarray], ndarray] | None = None, max_iterations: int | None = None) Tuple[ndarray, ndarray]

Performs an adaptive algorithm to improve a frequency range for calculation of the Fourier integral of func

The algorithm finds new frequencies by creating a [PCHIP] interpolaion of func on the frequencies, comparing that interpolation with the true function value the midpoints of all frequency subintervals, and using Simpson’s rule to evaluate the integral of the difference between the interpolation and the true function. The midpoint of the subinterval with the largest interpolation error is then added to the frequencies array.

This repeats either until max_iterations iterations have been performed, or until the interpolation error integral has a smaller total value than absolute_integral_tolerance

To avoid many repeated calls to func, the outputs are cached, so that reevaluation at the same frequency only amounts to a dictionary lookup.

func should only give finite outputs for all frequencies between the extremes of the input frequencies.

The improved frequency range will never exceed the boundaries of the input.

+-inf can be included in the frequency range, but user discretion is advised, as depending on func and step_towards_inf_factor, adding frequencies towards inf can come at the cost of not adding frequencies close to the most important features of func, since the frequency intervals added towards infinity can get very wide (they get gradually bigger), and this can overshadow shorter intervals where the error is larger.

The starting frequency range must contain at least 2 finite frequencies, and +-infinity requires the adjacent frequency to be finite, non-zero, and of the same sign.

It should be noted that while the algorithm will run with as little as 2 initial frequencies, it is for the best results advised to use a frequency range that already captures the most essential features of func, and thus use the algorithm to improve this range.

Based on the algorithm outlined in section 1.6.3 in [N.Mounet-PhD].

Parameters:
  • initial_frequencies (Sequence[float]) – A 1D array of floats containing the starting frequencies [Hz]* for the algorithm. Must contain at least 2 frequencies. Can contain +-np.inf.

  • func (Callable[[float], ArrayLike]) – The function to be Fourier integrated, a function of frequency [Hz]* with a complex output. Does not need to be vectorized. Results will be cached to avoid repeat calls with the same input.

  • interpolation_error_norm (Optional[Callable[[np.ndarray, np.ndarray], np.ndarray]]) – A callable that takes in an array of func outputs (shape (N, X1, X2, …)) and interpolated approximations of the same values (also shape (N, X1, X2, …)) The primary axis (of length N) corresponds to the frequency. The callable should return a norm of the difference between the two inputs, collapsed into a 1D array along the frequency axis, i.e. the output should have the shape (N,). If None (the default) is given, the norm will be calculated using the absolute difference for 1D arrays, or the 2-norm for higher dimension arrays

  • absolute_integral_tolerance (float) – The tolerance for the (approximate) integrated interpolation error. When the error drops below this value, the algorithm terminates.

  • step_towards_inf_factor (float, optional) – When one of the ends of the frequency array is +-inf, the bisection of the corresponding interval is calculated by multiplying the (finite) neighboring frequency with this number. Defaults to 2

  • bisection_mode_condition (Optional[Callable[[np.ndarray], np.ndarray]], optional) – A function that takes in a frequency array [Hz]* and returns an array of bools of the same size, where True denotes that the interval following that frequency should be bisected linearly, and False geometrically. Can be set to None, in which case only geometric bisection is used. Defaults to None

  • max_iterations (Optional[int], optional) – The maximum amount of iterations to perform before the algorithm is terminated. If set to None, the algorithm will only terminate after the tolerance has been met. Defaults to None

Returns:

The refined frequency range [Hz]*, and an array containing the corresponding outputs of func

Return type:

Tuple[np.ndarray, np.ndarray]

*Though Hz is used as units here, any frequency unit will work, just be mindful that if used in a Fourier integral the result will be in units 1/<frequency unit>

Package Internals

The following functions and classes are mainly of interest to developers of Neffint.

class neffint.fixed_grid_fourier_integral.InterpolationMode(value, names=None, *, module=None, qualname=None, type=None, start=1, boundary=None)

Bases: Enum

PCHIP = 'pchip'
LINEAR = 'linear'
neffint.fixed_grid_fourier_integral._lambda(x: _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | bool | int | float | complex | str | bytes | _NestedSequence[bool | int | float | complex | str | bytes]) ndarray

Calculates the Lambda function defined in equations E.136 in [N.Mounet-PhD], which is given by:

Lambda(x) = -j*exp(j*x)/x + (exp(j*x)-1)/x^2,

where j = sqrt(-1) is the imaginary unit.

For |x| < 1, a Taylor series approximation is summed until convergence is reached.

Parameters:

x (ArrayLike) – The input variable x, given as a single float or an array of floats.

Raises:

RuntimeError – If the Taylor series summation did not converge after 1000 iterations.

Returns:

Lambda, an array with the same shape as x

Return type:

np.ndarray

neffint.fixed_grid_fourier_integral._phi_and_psi(x: _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | bool | int | float | complex | str | bytes | _NestedSequence[bool | int | float | complex | str | bytes]) Tuple[ndarray, ndarray]

Calculates the Phi and Psi functions defined in equations E.142 and E.143 in [N.Mounet-PhD], which are given by:

Phi(x) = -j*exp(j*x)/x - 6j*(exp(j*x)+1)/x^3 + 12(exp(j*x)-1)/x^4,

Psi(x) = exp(j*x)/x^2 + 2j*(2*exp(j*x)+1)/x^3 - 6(exp(j*x)-1)/x^4,

Where j = sqrt(-1) is the imaginary unit.

For |x| < 1, a Taylor series approximation is summed until convergence is reached.

Parameters:

x (ArrayLike) – The input variable x, given as a single float or an array of floats.

Raises:

RuntimeError – If the Taylor series summation did not converge after 1000 iterations.

Returns:

Tuple of two arrays: Phi and Psi, with the same shape as x

Return type:

Tuple[np.ndarray, np.ndarray]

neffint.fixed_grid_fourier_integral._fourier_integral_inf_correction(times: _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | bool | int | float | complex | str | bytes | _NestedSequence[bool | int | float | complex | str | bytes], omega_end: float, func_value_end: _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | bool | int | float | complex | str | bytes | _NestedSequence[bool | int | float | complex | str | bytes], func_derivative_end: _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | bool | int | float | complex | str | bytes | _NestedSequence[bool | int | float | complex | str | bytes] = 0.0, positive_inf: bool = True) ndarray

Calculate the asymptotic correction term as omega -> +-inf of a Fourier integral for the given times. Uses a first or second (if func_derivative_end is given) order Taylor expansion around the angular frequency omega_end.

Parameters:
  • times (ArrayLike) – Float or 1D array of floats of length M, the time(s) [s]* to compute the fourier integral for

  • omega_end (float) – An angular frequency [rad/s]* to expand the Taylor series from. If positive_inf == True, this should be the highest angular frequency used. Otherwise, it should be the lowest (closest to -inf).

  • func_value_end (ArrayLike) – An array of shape (X1, X2, …) containing the values of the function to be transformed evaluated at omega_end

  • func_derivative_end (ArrayLike, optional) – An array of shape (X1, X2, …) containing the derivative of the function to be transformed, evaluated at omega_end, defaults to 0

  • positive_inf (bool, optional) – Flag set to True if the asymptotic correction towards +inf should be calculated, and False if the correction towards -inf should be calculated

Returns:

The asymptotic terms of the Fourier Integral for all times, given as an array of shape (M, X1, X2, …)

Return type:

np.ndarray

*Though the units s and rad/s are used here, any coherent set of time and angular frequency units will work

neffint.fixed_grid_fourier_integral.fourier_integral_fixed_sampling(times: _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | bool | int | float | complex | str | bytes | _NestedSequence[bool | int | float | complex | str | bytes], frequencies: _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | bool | int | float | complex | str | bytes | _NestedSequence[bool | int | float | complex | str | bytes], func_values: _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | bool | int | float | complex | str | bytes | _NestedSequence[bool | int | float | complex | str | bytes], pos_inf_correction_term: bool, neg_inf_correction_term: bool, interpolation: str) ndarray

Calculates the fourier integral of a function for the time values given as input:

integral from fmin to fmax of : exp(2*pi*j*f*t)*func(f)*df,

where t is the time, fmin is the first frequency in the input frequencies, fmax is either the highest frequency or (positive) infinity, depending on inf_correction_term, and func(f) is the input function of frequency. The function is given as an array of outputs corresponding to the array of frequencies given.

A Filon type algorithm using a either a piecewise cubic Hermite interpolating polynomial ([PCHIP]) or a piecewise linear polynomial, depending on the interpolation argument. Optionally, an asymptotic correction term can also be computed at each end. For details on implementation, see [N.Mounet-PhD].

Parameters:
  • times (ArrayLike) – Float or 1D array of floats of length M, the time(s) [s]* to compute the fourier integral for

  • frequencies (ArrayLike) – Float or 1D array of floats of length N, the frequencies [Hz]* the function to be transformed have been evaluated at

  • func_values (ArrayLike) – Complex or ND array of complex of shape (N, X1, X2, …), the outputs of the function to be transformed at the frequencies given as input

  • pos_inf_correction_term (bool) – True if an asymptotic correction term towards +infinity should be added, otherwise the integral is effectively truncated at the highest frequency

  • neg_inf_correction_term (bool) – True if an asymptotic correction term towards -infinity should be added, otherwise the integral is effectively truncated at the lowest (closest to -inf) frequency

  • interpolation (str) – String either equal to “pchip” or “linear”, to select the integration methods using PCHIP or piecewise linear interpolation, respectively.

Returns:

The fourier integral of the input function at the input times, given as an array of shape (M, X1, X2, …)

Return type:

np.ndarray

*Though the units s and Hz are used here, any coherent set of time and frequency units will work

neffint.fixed_grid_fourier_integral._fourier_integral_fixed_sampling_pchip(times: ndarray, omegas: ndarray, func_values: ndarray, func_derivatives: ndarray) ndarray
neffint.fixed_grid_fourier_integral._fourier_integral_fixed_sampling_linear(times: ndarray, omegas: ndarray, func_values: ndarray) ndarray