Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
fe1e9d0
Added boilerplate structure
martijnende Jul 23, 2025
74a50f5
Forward model working, but problem JIT caching
martijnende Jul 23, 2025
8c821a1
Fixed JIT caching
martijnende Jul 23, 2025
d851b52
Implemented first unit tests
martijnende Jul 23, 2025
31a7896
Added Github actions workflow (untested)
martijnende Jul 23, 2025
ec67103
Removed flake from workflow
martijnende Jul 23, 2025
864726d
Fixed duplicate code actions
martijnende Jul 23, 2025
beded66
Added documentation logic
martijnende Jul 23, 2025
f140dcb
Created actions workflow for docs
martijnende Jul 23, 2025
919a479
Levenberg-Marquardt inversion working
martijnende Jul 23, 2025
e5cf71e
Implemented test for LM inversion
martijnende Jul 24, 2025
8f7b18c
Created a basic example notebook
martijnende Jul 24, 2025
98a75ab
Added basic SVI functionalities (not tested)
martijnende Jul 24, 2025
a124bb4
Generalised typedefs a bit
martijnende Jul 24, 2025
83ebf87
Updated docs actions now that repo is public
martijnende Jul 24, 2025
43d01bb
Changed workflow titles for badges
martijnende Jul 24, 2025
fb6b62c
Updated README to include status badges
martijnende Jul 24, 2025
765c1ba
Added forward_models docstrings
martijnende Jul 25, 2025
308d513
Updated documentation building workflow to fix sphinx-apidoc
martijnende Jul 25, 2025
667033e
Changed workflow logic for better reuse
martijnende Jul 25, 2025
3d74ff2
Fixed file naming github actions
martijnende Jul 25, 2025
a70e0eb
Probably going to remove the Particles typedef logic later
martijnende Jul 25, 2025
c951bf7
Started implementing SVI, but bugs around every corner
martijnende Jul 29, 2025
9ddcbbe
Basic SVI working, still working on interface
martijnende Jul 31, 2025
0e04b04
Implemented SVI user interface (plots etc.)
martijnende Jul 31, 2025
4f1f603
Fixed circular import
martijnende Jul 31, 2025
0274b5f
Added SVI to example notebook (with several minor fixes)
martijnende Jul 31, 2025
4fa0014
Clean-up of unused imports
martijnende Aug 1, 2025
b77693d
Added extended documentation structure
martijnende Aug 1, 2025
a9935d4
Populated the getting started page
martijnende Aug 1, 2025
6391c20
Included infrastructure for references
martijnende Aug 1, 2025
6ea77fd
Added forward models documentation page
martijnende Aug 5, 2025
124869d
Added inverse models, fixed referencing
martijnende Aug 6, 2025
142a4e4
Populated RSF and spring-block documentation pages
martijnende Aug 6, 2025
ea530fa
Documented max-likelihood and Bayesian inversion (partially)
martijnende Aug 6, 2025
da633e3
Added SVI to docs
martijnende Aug 7, 2025
eddf912
Finalised SVI docs
martijnende Aug 7, 2025
c38f2d7
Some typo corrections
martijnende Aug 7, 2025
4ab5640
Started populating rock friction docs
martijnende Aug 7, 2025
61f11e6
Prior to recasting state evolution formalism
martijnende Aug 12, 2025
ddad42c
Implemented base Variables class and tested differentiability
martijnende Aug 18, 2025
37a97a9
A few small fixes before adjusting solver wrappers
martijnende Aug 18, 2025
c4cf8f9
New Variables class working with SciPy solve_ivp
martijnende Aug 18, 2025
c0b98b6
Inertial spring-block working, but equations are extremely stiff...
martijnende Aug 18, 2025
5c4ea8c
Changed automatic state variable discovery to user-defined assignment
martijnende Aug 20, 2025
c9dcdba
Made unit tests compatible with new data structure
martijnende Aug 21, 2025
642fe24
Finally got LM inversion test working...
martijnende Aug 25, 2025
b250f8d
Modified example to match new data structure. LM unstable
martijnende Aug 25, 2025
a9f68de
Managed to make SVI work, but converges to the wrong results!
martijnende Aug 26, 2025
4b50462
SVI and everything finally working again...
martijnende Aug 26, 2025
24c4486
Updated documentation to account for new data structure
martijnende Aug 28, 2025
b9de1f8
Figured out how to use autosummary/autodoc
martijnende Aug 28, 2025
411b219
Docstrings forward models
martijnende Aug 28, 2025
136c3e6
Added many more docstrings
martijnende Aug 29, 2025
1f76806
Docstrings of containers
martijnende Aug 29, 2025
366970b
Forgot to include .py in commit...
martijnende Aug 29, 2025
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
10 changes: 10 additions & 0 deletions .github/actions/setup/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
name: Setup project
description: Checkout code, install dependencies

runs:
using: "composite"
steps:
- name: Install dependencies
shell: bash
run: |
pip install .[dev,docs]
57 changes: 57 additions & 0 deletions .github/workflows/build-docs.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
name: documentation

on:
push:
branches: ["main", "dev"]

jobs:
build_docs:
runs-on: ubuntu-latest

steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.10"
- uses: ./.github/actions/setup

- name: Generate .rst files from package
run: |
sphinx-apidoc -o docs/source/api diabayes

- name: Build Sphinx HTML documentation
run: |
cd docs
make clean && make html

- name: Upload documentation artifact
uses: actions/upload-artifact@v4
with:
name: sphinx-html
path: docs/build/html

# Publish built docs to gh-pages branch
- name: Commit documentation changes
run: |
git clone https://${{ secrets.GH_TOKEN }}@github.com/martijnende/diabayes.git --branch gh-pages --single-branch gh-pages
cd gh-pages
git clean -fdx # Remove old untracked files and directories
cp -r ../docs/build/html/* . # Copy new HTML files to gh-pages
touch .nojekyll
git config --local user.email "action@github.com"
git config --local user.name "GitHub Action"
git add .
git commit -m "Update documentation" -a || true
# The above command will fail if no changes were present, so we ignore
# that.
env:
GH_PAT: ${{ secrets.GH_TOKEN }}

- name: Push changes
uses: ad-m/github-push-action@master
with:
branch: gh-pages
directory: gh-pages
GH_PAT: ${{ secrets.GH_TOKEN }}
26 changes: 26 additions & 0 deletions .github/workflows/python-test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
name: tests

on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]

permissions:
contents: read

jobs:
build:

runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4
- name: Set up Python 3.10
uses: actions/setup-python@v5
with:
python-version: "3.10"
- uses: ./.github/actions/setup
- name: Test with pytest
run: |
pytest
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
scratch/
.vscode/

# Byte-compiled / optimized / DLL files
__pycache__/
*.py[codz]
Expand Down Expand Up @@ -70,6 +73,8 @@ instance/

# Sphinx documentation
docs/_build/
docs/build/
docs/source/_autosummary

# PyBuilder
.pybuilder/
Expand Down
33 changes: 32 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,32 @@
# diabayes
# DiaBayes: rock friction inversion tools

[![GitHub Release](https://img.shields.io/github/release/martijnende/diabase.svg?style=flat)]()
[![tests](https://github.com/martijnende/diabayes/actions/workflows/python-test.yml/badge.svg)](https://github.com/martijnende/diabayes/actions/workflows/python-test.yml)
[![documentation](https://github.com/martijnende/diabayes/actions/workflows/build-docs.yml/badge.svg)](https://martijnende.github.io/diabayes)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
<!-- [![PyPi Version](https://img.shields.io/pypi/v/diabayes.svg)](https://pypi.python.org/pypi/diabayes/) -->

[Documentation](https://martijnende.github.io/diabayes) | [Example usage](#example-usage) | [Installation](#installation) | [How to cite?](#how-to-cite)

## Example usage

See `examples/simple_example.ipynb` for a self-contained Jupyter notebook that illustrates forward and inverse modelling.

## Installation

Installing the latest version with CPU support from GitHub:
```bash
pip install git@github.com:martijnende/diabayes.git
```
Installing from a local repository with Nvidia GPU support (CUDA version 12):
```bash
cd /path/to/diabase && pip install .[gpu]
```
If you plan to contribute to the development of this package, please include the development tools:
```bash
pip install .[gpu,dev]
```

## How to cite?

A publication describing this software package is underway. Until then, feel free to refer to this repository.
108 changes: 108 additions & 0 deletions diabayes/SVI.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
from typing import Callable, TypeAlias

import equinox as eqx
import jax
import jax.numpy as jnp
from jaxtyping import Array, Float

from diabayes.typedefs import Variables, _Params

ParticleArray = Float[Array, "N M"]
GradientArray: TypeAlias = ParticleArray


@eqx.filter_jit
def _distance(x1: ParticleArray, x2: ParticleArray) -> Float[Array, "N N"]:
"""Euclidean distance between two particles `x1` and `x2`"""
return jnp.square(x1 - x2).sum(axis=-1)


@eqx.filter_jit
def _exponential_kernel(
x1: ParticleArray, x2: ParticleArray, h: float
) -> Float[Array, "N N"]:
"""Radial basis distance between two particles `x1` and `x2`"""
dist_sq = _distance(x1, x2)
return jnp.exp(-dist_sq / h)


@eqx.filter_jit
def _median_trick_h(x: ParticleArray) -> Float:
"""
Compute the scaling factor `h` proportional to the
squared median of the RMS distance between all pairs
of particles.
"""
dist_sq = jnp.square(x[:, None] - x[None]).sum(axis=-1)
# Replace this one with jnp.nanmedian to avoid spreading NaNs?
med_sq = jnp.median(jnp.sqrt(dist_sq))
h = med_sq**2 / jnp.log(len(x) + 1)
return h


@eqx.filter_jit
def compute_phi(
x: ParticleArray, gradp: GradientArray, gradq: GradientArray
) -> GradientArray:
"""
Compute the Stein variational gradients for a set of
particles (``x``) and the gradients of the log-likelihood
function (``gradp``) and the log-prior (``gradq``).

Parameters
----------
x : ParticleArray
The set of invertible parameters ("particles")
of shape ``(Nparticles, Ndimensions)``
gradp, gradq : GradientArray
The gradients of the log-likelihood (``gradp``) and the
log-prior (``gradq``) with respect to the invertible parameters.
Has a shape ``(Nparticles, Ndimensions)``

Returns
-------
grad_x : Gradients
The directional gradients for the particle updates, e.g.
``new_x = x + step_size * grad_x``. Has the same
shape as ``x`` and ``gradp, gradq``.
"""
h = _median_trick_h(x)
map_over_a = (0, None, None)
map_over_b = (None, 0, None)

map1 = jax.vmap(_exponential_kernel, map_over_a, 0)
kernel = jax.vmap(map1, map_over_b, 1)
K = kernel(x, x, h)

map1 = jax.vmap(jax.grad(_exponential_kernel), map_over_a, 0)
grad_kernel = jax.vmap(map1, map_over_b, 1)
grad_K = grad_kernel(x, x, h).sum(axis=0)

grad_x = (jnp.matmul(K, gradp) + jnp.matmul(K, gradq) + grad_K) / len(gradp)
return -grad_x


@eqx.filter_value_and_grad
def _log_likelihood(
log_params: _Params,
mu_obs: Float[Array, "Nt"],
noise_std: Float,
forward_fn: Callable[[_Params], Variables],
) -> Float:
# Transform the log_params by taking exponential
params = type(log_params).from_array(jnp.exp(log_params.to_array()))
# Forward pass to get friction curve
mu_hat = jnp.squeeze(forward_fn(params).mu)
# Log-likelihood of residuals
p = -(jnp.square(mu_obs - mu_hat).mean() / (2 * noise_std**2))
return p


"""
vmap _log_likelihood along particle axis. Since _log_likelihood is
decorated with eqx.filter_value_and_grad, it returns the log-
likelihood and its gradient (hence it needs 2 values for the out_axes).
"""
mapped_log_likelihood = jax.vmap(
_log_likelihood, in_axes=(0, None, None, None), out_axes=(0, 0)
)
7 changes: 7 additions & 0 deletions diabayes/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
from diabayes.typedefs import (
BayesianSolution,
RSFConstants,
RSFParams,
SpringBlockConstants,
Variables,
)
Loading
Loading