Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 4 additions & 38 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -18,53 +18,19 @@
Introduction
============

This package implements wavelet based multifractal analysis of 1D signals.
This package implements wavelet-based multifractal analysis of 1D signals.

Implemented features:

* Computation of (1D) multiresolution quantities: wavelet coefficients, wavelet-leaders and p-leaders
* Computation of (1D) multiresolution quantities: wavelet coefficients, wavelet-leaders and p-leaders.
* Computation of structure functions, cumulants and log-cumulants.
* Estimation of the multifractal spectrum.
* Bivariate multifractal analysis.
* Bootstrap-derived confidence intervals and automated scaling range selection.
* Outlier detection.


The initial implementation of the code in this package was based on the Wavelet p-Leader and Bootstrap based MultiFractal analysis (PLBMF) `Matlab toolbox <http://www.ens-lyon.fr/PHYSIQUE/Equipe3/MultiFracs/software.html>`_ written by Patrice Abry, Herwig Wendt and colleagues. For a thorough introduction to multifractal analysis, you may access H. Wendt's PhD thesis available in `his website <https://www.irit.fr/~Herwig.Wendt/data/ThesisWendt.pdf)>`_.

To get started, please look at our :doc:`documentation <user_guide/index>`.

.. For a brief introduction to multifractal analysis, see the file THEORY.ipynb

There are two ways to install this package: either by using a package manager to install the package only, which will make
the code only usable as an import,
or by cloning the repository first, and then installing the package which will make it editable

Installing the package only
===========================

.. code:: shell

wget https://raw.githubusercontent.com/neurospin/pymultifracs/master/env.yml
conda env update -f env.yml --name $ENVNAME

----

Using pip
---------

.. code:: shell

pip install git+https://github.com/neurospin/pymultifracs



Cloning the whole repository (including examples)
=================================================


.. code:: shell

git clone https://github.com/neurospin/pymultifracs
pip install -e pymultifracs

For examples to get started, look into the `example/` folder
.. include:: Installation.rst
34 changes: 34 additions & 0 deletions doc/Installation.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
Installing PyMultifracs
-----------------------

There are two ways to install this package: either by using a package manager to install the package only, which will make
the code only usable as an import,
or by cloning the repository first, and then installing the package which will make it editable.

Using pip (not editable)
************************

.. code:: shell

pip install git+https://github.com/neurospin/pymultifracs


Cloning the whole repository (including examples)
*************************************************

.. code:: shell

git clone https://github.com/neurospin/pymultifracs
pip install -e pymultifracs

For examples, look into the `examples/` folder, or alternatively find them in the :doc:`documentation <auto_examples/index>`.

Optional features
*****************

In order to avoid download unnecessary packages, by default only the essential dependencies are installed.
To use all the features of the toolbox, you can do a full install by providing :code:`[full]`. For instance, after cloning the repository:

.. code:: shell

pip install -e pymultifracs[full]
8 changes: 8 additions & 0 deletions doc/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -396,6 +396,14 @@
'.md': 'markdown'
}

myst_enable_extensions = [
"colon_fence",
"deflist",
"dollarmath",
"smartquotes",
# "amsmath"
]

# %% Adjusting the displayed name of functions
# https://stackoverflow.com/a/72658470

Expand Down
3 changes: 2 additions & 1 deletion doc/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ Contents
:maxdepth: 1
:caption: Overview:

reference
User Guide <user_guide/index>
API reference <reference>
auto_examples/index
version_updates
14 changes: 14 additions & 0 deletions doc/markdown/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
```{eval-rst}
.. include:: ../README.rst
```

# Contents

```{toctree}
:depth: 1
:caption: Overview:
user_guide.md
reference.rst
auto_examples/index.rst
version_updates.rst
```
6 changes: 3 additions & 3 deletions doc/reference.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
=============
API Reference
=============
======================
PyMultifracs Reference
======================

Multifractal Analysis
=====================
Expand Down
37 changes: 37 additions & 0 deletions doc/user_guide/basics_scaleinvariance.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# Basics of scale invariance analysis

Let us first clarify what is scale invariance

## Scale invariance

Consider the Koch fractal:

This notion of invariance to scaling operations can be extended to a larger class of functions, where the preserved property is not the exact shape but rather a quantity that is derived from the function over different scales.

The Brownian motion is an example of scale invariant random process, where the statistical properties of the process do not depend on the scale at which it is considered:

More formally, the notion of scale invariance is connected to the idea of **power law**, which describes scaling relationships $f$ along a variable $x$ of the following nature:
:::{math}
f(x) \propto x^{\alpha} \, .
:::

Where $\alpha$ is the **scaling exponent** of the power-law. We can see that it exhibits scale invariance, as rescaling by a particular lengthscale $b$ preserves the nature of the relationship and the power-law exponent:
```{math}
f(x/b) \propto b^{-\alpha} x^{\alpha} \propto x^{\alpha} \, .
```

### Hurst exponent

In general, for a scale invariant random process $X(t)$ we can define the **Hurst exponent** $H\in(0, 1)$, which characterizes the behavior of the process under rescaling:
$$
X(ct) = c^H X(t) \,.
$$

Brownian motion has a Hurst exponent $H=0.5$; there is a natural extension of Brownian motion that has an adjustable Hurst exponent: the **fractional Brownian motion** (fBM) model. An fBm $Y(t)$ with Hurst exponent $H$ is defined by its autocorrelation function:

$$
\mathbb{E}\left[ Y(t) Y(s) \right] = \frac{1}{2} \left( |t|^{2H} + |s|^{2H} - |t - s|^{2H} \right)\,.
$$

## Second-order analysis

1 change: 1 addition & 0 deletions doc/user_guide/bootstrap.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Bootstrapping for multifractal analysis
1 change: 1 addition & 0 deletions doc/user_guide/features_pmfa.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Main features of the PyMultiFracs toolbox
28 changes: 28 additions & 0 deletions doc/user_guide/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# PyMultiFracs user guide

This guide is an introduction to multifractal analysis with PyMultiFracs.

```{toctree}
:caption: Getting started
:maxdepth: 1

whatismfa
../Installation.rst
quickstart
```

<!-- ```{toctree}
:caption: Fundamentals and usage
:maxdepth: 2

basics_scaleinvariance
features_pmfa
```

```{toctree}
:caption: Advanced usage
:maxdepth: 1

bootstrap
outlier_detection
``` -->
1 change: 1 addition & 0 deletions doc/user_guide/outlier_detection.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Detection of outliers
1 change: 1 addition & 0 deletions doc/user_guide/quickstart.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# PyMultiFracs quickstart
2 changes: 2 additions & 0 deletions doc/user_guide/whatismfa.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# What is multifractal analysis?

64 changes: 35 additions & 29 deletions examples/01-simul.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,23 +40,26 @@
# -----------------

# %% [markdown]
# Wavelet transform is performed the :func:`pymultifracs.wavelet_analysis`
# Wavelet transform is performed the :func:`~pymultifracs.wavelet_analysis`
# function
#
# Parameters:
# **Parameters**
#
# - ``wt_name``: The discrete wavelet to use, following the convention of the
# :mod:`pywavelets` package.
# ``wt_name``
# The discrete wavelet to use, following the convention of the
# :mod:`pywavelet` package.
#
# - ``j2``: The largest scale to analyze, by default ``None`` which means that
# the analysis is carried to the coarsest possible temporal scale. The
# motivation for setting a lower value is to reduce the computation time and
# memory footprint.
# ``j2``
# The largest scale to analyze, by default ``None`` which means that
# the analysis is carried to the coarsest possible temporal scale. The
# motivation for setting a lower value is to reduce the computation time and
# memory footprint.
#
# - ``normalization``: Normalization norm for the wavelet coefficients: takes
# the value of :math:`p` to define the :math:`p`-norm used in normalization.
# Defaults to 1 (:math:`1`-norm) which is appropriate for scale invariance
# analysis.
# ``normalization``
# Normalization norm for the wavelet coefficients: takes
# the value of :math:`p` to define the :math:`p`-norm used in normalization.
# Defaults to 1 (:math:`1`-norm) which is appropriate for scale invariance
# analysis.
#
# Multivariate time series, such as we are dealing with here, are passed with
# the shape `(n_samples, n_channels)`
Expand All @@ -79,8 +82,8 @@

# %% [markdown]
# Multi-resolution quantities derived from the wavelet transform can be
# obtained using the associated methods :meth:`.WaveletDec.get_leaders` and
# :meth:`.WaveletDec.get_wse`:
# obtained using the associated methods :meth:`~.WaveletDec.get_leaders` and
# :meth:`~.WaveletDec.get_wse`:

# %%
WTL = WT.get_leaders(p_exp=np.inf)
Expand Down Expand Up @@ -111,7 +114,7 @@
# In order for the analysis to be meaningful under the chosen multifractal
# formalism (wavelet coefficient, wavelet (p-)leader, etc.) it may be necessary
# to verify a minimum regularity condition.
# The method :meth:`.WaveletDec.check_regularity` is available with all
# The method :meth:`~.WaveletDec.check_regularity` is available with all
# multi-resolution quantities, and takes ``scaling_ranges`` as an argument:

# %%
Expand All @@ -124,7 +127,7 @@
# In case the minimal regularity is too low, it may be necessary to
# fractionally integrate the time series.
#
# A simple approach is provided in the :meth:`.WaveletDec.auto_integrate`
# A simple approach is provided in the :meth:`~.WaveletDec.auto_integrate`
# method, which will try to find a fractional integration coefficient large
# enough that all signals may be analyzed, and return the properly integrated
# multi-resolution quantity.
Expand All @@ -135,7 +138,7 @@
# %% [markdown]
# Otherwise, and for instance in the case where multiple sets of data need to
# be compared using the same integration coefficient, the fractional
# integration can be set using the :meth:`.WaveletDec.integrate` method on a
# integration can be set using the :meth:`~.WaveletDec.integrate` method on a
# MRQ object by passing the fractional integration coefficient :math:`\gamma`:

# %%
Expand All @@ -148,17 +151,20 @@
# %% [markdown]
# Multifractal analysis is carried out using the :func:`mfa` function.
#
# Basic parameters:
# **Basic parameters**
#
# - ``mrq``: Multi-resolution quantity (:class:`.WaveletDec`,
# :class:`.WaveletLeader`, :class:`.WaveletWSE`) on which to perform the
# analysis.
# ``mrq``
# Multi-resolution quantity (:class:`.WaveletDec`,
# :class:`.WaveletLeader`, :class:`.WaveletWSE`) on which to perform the
# analysis.
#
# - ``weighted``: whether the linear regressions should be weighted. Defaults
# to None, which means no weighting is performed. ``"Nj"`` indicates that the
# weights are determined from the number of coefficients at each scale.
# ``weighted``
# whether the linear regressions should be weighted. Defaults
# to None, which means no weighting is performed. ``"Nj"`` indicates that the
# weights are determined from the number of coefficients at each scale.
#
# - ``q``: list of moments.
# ``q``
# list of moments.
#
# .. note:: by default, :func:`mfa` checks the regularity of the time series.
# It is possible to disable this by passing ``check_regularity=False``.
Expand All @@ -173,10 +179,10 @@
# The function outputs a :class:`.MFractalVar` object, which contains:
#
# - ``structure``: the structure functions (:class:`.StructureFunction`) and
# associated exponents
# associated exponents
#
# - ``cumulants``: the cumulant scaling functions (:class:`.Cumulants`) and
# log-cumulants
# log-cumulants
#
# - ``spectrum``: the multifractal spectrum (:class:`.MFSpectrum`)

Expand All @@ -187,13 +193,13 @@

# %% [markdown]
# The structure functions :math:`S_q(j)` and their associated exponents may be
# visualized using the :meth:`.StructureFunction.plot()` method
# visualized using the :meth:`~.StructureFunction.plot()` method

# %%
pwt.structure.plot(figsize=(10, 4), nrow=2)

# %% [markdown]
# We can plot :math:`\zeta(q)` using the :meth:`StructureFunction.plot_scaling`
# We can plot :math:`\zeta(q)` using the :meth:`~.StructureFunction.plot_scaling`
# method

# %%
Expand Down
16 changes: 10 additions & 6 deletions examples/02-bootstrap.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,12 @@
"""

# %% [markdown]
# Bootstrapping may be used in `pymultifracs` to determine empirical confidence intervals for the estimates (scaling functions, exponents), as well as an automated determination of the optimal scaling range among multiple choices.
# Bootstrapping may be used in `PyMultiFracs` to determine empirical confidence
# intervals for the estimates (scaling functions, exponents), as well as an
# automated determination of the optimal scaling range among multiple choices.
#
# Let us first generate a Multifractal Random Walks with parameters :math:`H = 0.8` and :math:`\lambda=\sqrt{0.05}`
# Let us first generate a Multifractal Random Walks with parameters
# :math:`H = 0.8` and :math:`\lambda=\sqrt{0.05}`

# %% [python]

Expand Down Expand Up @@ -45,10 +48,9 @@
WT = wavelet_analysis(X, wt_name='db3', j2=None, normalization=1)
WTpL = WT.get_leaders(p_exp=2)

# %%

# %% [markdown]
# The simplest way to use bootstrapping is to include the `R` parameter in
# calling :func:`mfa`, which will perform :math:`R > 1` bootstrapping
# calling :func:`~pymultifracs.mfa`, which will perform :math:`R > 1` bootstrapping
# repetitions prior to carrying out the multifractal analysis

from pymultifracs import mfa
Expand Down Expand Up @@ -81,7 +83,9 @@

pwt = mfa(WTpL, [(2, 8), (3, 8), (2, 7), (3, 7)], weighted=None, R=20)

# %% To determine the optimal scale, the :meth:`.ScalingFunction.find_best_range()` method is used:
# %%
# To determine the optimal scale, the
# :meth:`~pymultifracs.scalingfunction.Cumulants.find_best_range()` method is used:

pwt.cumulants.find_best_range()

Expand Down
Loading