Source code for pyrfu.pyrf.pvi

#!/usr/bin/env python
# -*- coding: utf-8 -*-

# 3rd party imports
import numpy as np
import xarray as xr

__author__ = "Louis Richard"
__email__ = "louis.richard@physics.ox.ac.uk"
__copyright__ = "Copyright 2020-2023"
__license__ = "MIT"
__version__ = "2.4.2"
__status__ = "Prototype"


[docs]def pvi(inp, scale: int = 10): r"""Returns the Partial Variance of Increments (PVI) of a time series. .. math:: PVI_i = \frac{|x_{i+s} - x_i|}{\sqrt{<|x_{i+s} - x_i|^2>}} where :math:`s` is the scale and the average :math:`<.>` is taken over the whole interval, ignoring NaNs [1]_. The increment :math:`x_{i+s} - x_i` is given at the time of :math:`x_i`. Parameters ---------- inp : xarray.DataArray Input time series. scale : int, Optional Scale at which to compute the PVI, in number of samples. Default is 10. Returns ------- values : xarray.DataArray An xarray containing the pvi of the original time series. Raises ------ ValueError If scale is not a positive integer. References ---------- .. [1] Greco, A., P. Chuychai, W. H. Matthaeus, S. Servidio, and P. Dmitruk (2008), Intermittent MHD structures and classical discontinuities, Geophys. Res. Lett., 35, L19111, doi: https://doi.org/10.1029/2008GL035454. """ if not isinstance(scale, (int, np.integer)) or scale < 1: raise ValueError("scale must be a positive integer") if len(inp.data.shape) == 1: data = inp.data[:, np.newaxis] else: data = inp.data delta_inp = np.abs((data[scale:, :] - data[:-scale, :])) delta_inp2 = np.sum(delta_inp**2, axis=1) sigma = np.nanmean(delta_inp2) result = np.sqrt(delta_inp2 / sigma) time = inp.coords[inp.dims[0]].data attrs = {k: v for k, v in inp.attrs.items() if k != "UNITS"} result = xr.DataArray( result, coords=[time[0 : len(delta_inp)]], dims=[inp.dims[0]], attrs=attrs, ) result.attrs["units"] = "dimensionless" result.attrs["TENSOR_ORDER"] = 0 return result