Metadata-Version: 2.2
Name: inv_toolbox
Version: 0.1.0
Summary: A python toolbox for inverse problem resolution (preconditioning, regularization, finite differences, etc.).
Author-email: Antoine Collet <antoinecollet5@gmail.com>
License: BSD 3-Clause License
        
        Copyright (c) 2026, Antoine COLLET
        All rights reserved.
        
        Redistribution and use in source and binary forms, with or without
        modification, are permitted provided that the following conditions are met:
        
        1. Redistributions of source code must retain the above copyright notice, this
           list of conditions and the following disclaimer.
        
        2. Redistributions in binary form must reproduce the above copyright notice,
           this list of conditions and the following disclaimer in the documentation
           and/or other materials provided with the distribution.
        
        3. Neither the name of the copyright holder nor the names of its
           contributors may be used to endorse or promote products derived from
           this software without specific prior written permission.
        
        THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
        AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
        DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
        FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
        SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
        CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
        OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
        OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
        
Project-URL: Homepage, https://pypi.org/project/inv_toolbox/
Project-URL: Documentation, https://inv-toolbox.readthedocs.io/en/latest/
Project-URL: Repository, https://github.com/antoinecollet5/inv_toolbox
Project-URL: Issues, https://github.com/antoinecollet5/inv_toolbox/issues
Project-URL: Changelog, https://github.com/antoinecollet5/inv_toolbox/blob/master/CHANGELOG.rst
Keywords: Covariance,Regularization,Preconditioner,Inverse problem,Finite differences
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: Natural Language :: English
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Requires-Python: >=3.10
Description-Content-Type: text/x-rst
License-File: LICENSE
License-File: AUTHORS.rst
Requires-Dist: setuptools
Requires-Dist: wheel
Requires-Dist: numpy>=1.2
Requires-Dist: scipy>=1.6.2
Requires-Dist: covmats>=0.5.0
Requires-Dist: quickpaver>=0.4.0
Requires-Dist: packaging
Requires-Dist: typing_extensions
Requires-Dist: nested_grid_plotter>=2.1.1
Requires-Dist: numdifftools
Provides-Extra: all
Requires-Dist: inv_toolbox[docs,examples,install,lint,tests]; extra == "all"
Provides-Extra: docs
Requires-Dist: inv_toolbox[examples]; extra == "docs"
Requires-Dist: sphinx<9; extra == "docs"
Requires-Dist: nbsphinx; extra == "docs"
Requires-Dist: nbsphinx-link>=1.3.1; extra == "docs"
Requires-Dist: jupyter_sphinx>=0.3.2; extra == "docs"
Requires-Dist: sphinx-jsonschema>=1.15; extra == "docs"
Requires-Dist: pygments>=2.11.1; extra == "docs"
Requires-Dist: pydata-sphinx-theme; extra == "docs"
Requires-Dist: sphinxcontrib-bibtex; extra == "docs"
Requires-Dist: sphinx_math_dollar; extra == "docs"
Requires-Dist: jupytext; extra == "docs"
Provides-Extra: tests
Requires-Dist: twine==1.14.0; extra == "tests"
Requires-Dist: pytest; extra == "tests"
Requires-Dist: pytest-runner; extra == "tests"
Requires-Dist: pytest-cov; extra == "tests"
Requires-Dist: pytest-cookies; extra == "tests"
Requires-Dist: coverage; extra == "tests"
Provides-Extra: examples
Requires-Dist: matplotlib; extra == "examples"
Requires-Dist: marimo; extra == "examples"
Provides-Extra: lint
Requires-Dist: pre-commit; extra == "lint"
Requires-Dist: pre-commit-hooks; extra == "lint"
Requires-Dist: codespell>=2.1.0; extra == "lint"
Requires-Dist: ruff; extra == "lint"
Requires-Dist: ty==0.0.80; extra == "lint"
Provides-Extra: install
Requires-Dist: pip; extra == "install"
Requires-Dist: wheel; extra == "install"

============
inv_toolbox
============

|License| |Stars| |Python| |PyPI| |Downloads| |Build Status| |Documentation Status| |Codacy| |Coverage| |Precommit: enabled| |Ruff| |ty|

🐍 A toolbox for inverse problem resolution.

**The complete and up to date documentation can be found here**: https://inv-toolbox.readthedocs.io.

===============
🎯 Motivations
===============

Solving an inverse problem (calibrating a geoscience model against observed data, for
instance) usually means minimizing a cost function made of a data-misfit term and one
or several regularization terms, then checking that the gradients fed to the optimizer
are actually correct. Each of these steps relies on a handful of recurring numerical
building blocks: spatial regularizators, parameter pre-transformations
(preconditioners), finite-difference approximations to validate analytical gradients,
and a few plotting helpers to inspect the result.

`inv_toolbox` gathers these building blocks behind a small, consistent, object-oriented
API so that they don't have to be reimplemented for every new inversion project. It
builds on `quickpaver <https://pypi.org/project/quickpaver>`_ for the regular grids
used by the local regularizators, and on
`covmats <https://github.com/antoinecollet5/covmats>`_ for the covariance matrix
representations used by the geostatistical regularizator.

===============
🚀 Quick start
===============

To install `inv_toolbox`, the easiest way is through `pip`:

.. code-block::

    pip install inv_toolbox

Or alternatively using `conda`

.. code-block::

    conda install inv_toolbox

You might also clone the repository and install from source

.. code-block::

    pip install -e .

Once the installation is done, `inv_toolbox` is straightforward to use and proposes
three submodules: `regularization`, `utils` and `plot`.

Let's start by importing `numpy`, `quickpaver` and `inv_toolbox` for the tests:

.. code-block:: python

    import numpy as np
    import quickpaver
    import inv_toolbox

Regularization
~~~~~~~~~~~~~~~

Local regularizators
^^^^^^^^^^^^^^^^^^^^^

`TikhonovRegularizator` penalizes spatial roughness of a field defined on a
`quickpaver.RectilinearGrid`, favoring smooth solutions. `TVRegularizator` uses a
total variation penalty instead, favoring blocky (piecewise constant) solutions.
Both are also available in a sparse-matrix form (`TikhonovMatRegularizator`,
`TVMatRegularizator`) and in a finite-volume form (`TikhonovFVMRegularizator`,
`TVFVMRegularizator`):

.. code-block:: python

    grid = quickpaver.RectilinearGrid(nx=15, ny=26, dx=3.6, dy=7.5)
    reg = inv_toolbox.regularization.TikhonovRegularizator(grid)

    rng = np.random.default_rng(2026)
    values = rng.random(grid.nx * grid.ny)
    reg.eval_loss(values)

.. code-block:: python

    3.2932279607534594

Every `Regularizator` exposes `eval_loss` as well as
`eval_loss_gradient_analytical`, so the gradient can be checked against a
finite-difference approximation with `inv_toolbox.utils.is_gradient_correct`:

.. code-block:: python

    inv_toolbox.utils.is_gradient_correct(
        values, reg.eval_loss, reg.eval_loss_gradient_analytical
    )

.. code-block:: python

    True

`DiscreteRegularizator` pulls a field toward a fixed set of discrete modes (for
facies or lithology parametrizations), and `ProbDistFitting` regularizes toward a
target empirical distribution.

Geostatistical regularizator
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

`GeostatisticalRegularizator` penalizes deviation from a prior using a parameter
covariance matrix supplied as a `covmats.CovarianceMatrix` (any of the
representations from `covmats`, dense or low-rank, can be used):

.. code-block:: python

    import covmats

    cov_m = covmats.CovViaDiagonal([1.0, 2.0, 3.0])
    reg = inv_toolbox.regularization.GeostatisticalRegularizator(cov_m)
    reg.eval_loss(np.array([4.0, -2.0, 5.0]))

.. code-block:: python

    13.166666666666666

An optional `covmats.PriorTerm` (e.g. a `ConstantPriorTerm` or a
`LinearDriftMatrix`-based term) can be passed to regularize toward something other
than zero.

Regularization weight strategies
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

The relative weight between the data-misfit and the regularization terms can be kept
`ConstantRegWeight` or updated on the fly with an `AdaptiveRegweight` strategy
(`AdaptiveUCRegweight`, `AdaptiveGradientNormRegweight`), and `get_l_curvature` helps
pick a weight from an L-curve analysis.

Utils
~~~~~~

`inv_toolbox.utils` provides the supporting numerical tools used above and
throughout an inversion workflow:

- Finite differences: `finite_gradient` and `finite_jacobian` compute
  finite-difference approximations of a gradient/Jacobian, and
  `is_gradient_correct`/`is_jacobian_correct` compare them against an analytical
  implementation, as shown earlier.
- Preconditioners: `Preconditioner` subclasses (`LogTransform`, `SqrtTransform`,
  `BoundsRescaler`, `StdRescaler`, `Normalizer`, `ChainedTransforms`, ...) implement
  variable changes applied to the parameters before the cost function is evaluated,
  to ease the optimizer's job or enforce constraints:

.. code-block:: python

    from inv_toolbox.utils.preconditioner import LogTransform

    LogTransform()(np.array([1.0, 10.0, 100.0]))

.. code-block:: python

    array([0.        , 2.30258509, 4.60517019])

- Spatial differential operators (`gradient_ffd`, `gradient_bfd`, `hessian_cfd`) and
  mean operators (`arithmetic_mean`, `harmonic_mean`, with their derivatives) used to
  build the regularizators above.
- Regular-grid helpers (`get_pts_coords_regular_grid`, `indices_to_node_number`,
  `get_array_borders_selection_2d`, ...) and spatial filters (`GaussianFilter`) to
  manipulate gridded parameter fields.

Plot
~~~~~

`inv_toolbox.plot` provides a few Matplotlib-based helpers to inspect inversion
results: `plot_observed_vs_simulated` for a calibration scatter plot,
`plot_percentiles` for ensemble percentile plots, and `plot_2d_grad_res_adj_vs_fd` to
visually compare an adjoint (or reverse-mode) gradient against its finite-difference
approximation.

===========
🔑 License
===========

This project is released under the **BSD 3-Clause License**.

Copyright (c) 2026, Antoine COLLET. All rights reserved.

For more details, see the `LICENSE <https://github.com/antoinecollet5/inv_toolbox/blob/master/LICENSE>`_ file included in this repository.

==============
⚠️ Disclaimer
==============

This software is provided "as is", without warranty of any kind, express or implied,
including but not limited to the warranties of merchantability, fitness for a particular purpose,
or non-infringement. In no event shall the authors or copyright holders be liable for
any claim, damages, or other liability, whether in an action of contract, tort,
or otherwise, arising from, out of, or in connection with the software or the use
or other dealings in the software.

By using this software, you agree to accept full responsibility for any consequences,
and you waive any claims against the authors or contributors.

==========
📧 Contact
==========

For questions, suggestions, or contributions, you can reach out via:

- Email: antoine.collet5@gmail.com
- GitHub: https://github.com/antoinecollet5/inv_toolbox

We welcome contributions!

=============
📚 References
=============

TODO

* Free software: SPDX-License-Identifier: BSD-3-Clause

.. |License| image:: https://img.shields.io/badge/License-BSD_3--Clause-blue.svg
    :target: https://github.com/antoinecollet5/inv_toolbox/blob/master/LICENSE

.. |Stars| image:: https://img.shields.io/github/stars/antoinecollet5/inv_toolbox.svg?style=social&label=Star&maxAge=2592000
    :target: https://github.com/antoinecollet5/inv_toolbox/stargazers
    :alt: Stars

.. |Python| image:: https://img.shields.io/pypi/pyversions/inv_toolbox.svg
    :target: https://pypi.org/pypi/inv_toolbox
    :alt: Python

.. |PyPI| image:: https://img.shields.io/pypi/v/inv_toolbox.svg
    :target: https://pypi.org/pypi/inv_toolbox
    :alt: PyPI

.. |Downloads| image:: https://static.pepy.tech/badge/inv_toolbox
    :target: https://pepy.tech/project/inv_toolbox
    :alt: Downloads

.. |Build Status| image:: https://github.com/antoinecollet5/inv_toolbox/actions/workflows/main.yml/badge.svg
    :target: https://github.com/antoinecollet5/inv_toolbox/actions/workflows/main.yml
    :alt: Build Status

.. |Documentation Status| image:: https://readthedocs.org/projects/inv_toolbox/badge/?version=latest
    :target: https://inv-toolbox.readthedocs.io/en/latest/?badge=latest
    :alt: Documentation Status

.. |Coverage| image:: https://codecov.io/gh/antoinecollet5/inv_toolbox/graph/badge.svg?token=oY3XZ1QTz3
    :target: https://codecov.io/gh/antoinecollet5/inv_toolbox
    :alt: Coverage

.. |Codacy| image:: https://app.codacy.com/project/badge/Grade/ec9b9a76589c4b3d867c92ddb0e8e19a
    :target: https://app.codacy.com/gh/antoinecollet5/inv_toolbox/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_grade
    :alt: codacy

.. |Precommit: enabled| image:: https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit
   :target: https://github.com/pre-commit/pre-commit

.. |Ruff| image:: https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json
    :target: https://github.com/astral-sh/ruff
    :alt: Ruff

.. |ty| image:: https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ty/main/assets/badge/v0.json
    :target: https://github.com/astral-sh/ty
    :alt: Checked with ty

.. |DOI| image:: https://zenodo.org/badge/DOI/10.5281/zenodo.18900358.svg
   :target: https://doi.org/10.5281/zenodo.18900358
