Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
0a8c79a
:sparkles: Creation of the PKLMTest class. Implement the first methos…
adriencrtrcap Aug 5, 2024
8730f96
:white_check_mark: Add and improve some tests
adriencrtrcap Aug 6, 2024
33b95ce
:rocket: Ends the test implementation and associated tests.
adriencrtrcap Aug 7, 2024
0601f2d
:poop: Implement the 'exact' p_value computation but results are not …
adriencrtrcap Aug 8, 2024
8f105e5
:sparkles: Start to support mixed data types.
adriencrtrcap Aug 8, 2024
e48dd4f
:sparkles: Add the feature to deal ith mixed data types and pandas da…
adriencrtrcap Aug 9, 2024
0374dec
:sparkles: Add the partial p-values feature.
adriencrtrcap Aug 28, 2024
c954180
:memo: Update the tutorial with the partial p-values section.
adriencrtrcap Aug 28, 2024
f91f421
Developp the "parameters and hyper-parameters" section in the tutoria…
adriencrtrcap Aug 28, 2024
102c027
Delete notebok
adriencrtrcap Aug 28, 2024
234a5a1
:fire: Remove useless code & Move some generic functions into utils f…
adriencrtrcap Aug 30, 2024
574f3db
:sparkles: When it's possible, take all the projections for small dat…
adriencrtrcap Aug 30, 2024
8ddc3dd
:bug: Patch the 'Category encoder bug'.
adriencrtrcap Sep 3, 2024
5b988ec
Typo in docstring
adriencrtrcap Sep 3, 2024
ab61060
Detail some dostrings and fix typo in the tuto
adriencrtrcap Sep 6, 2024
dcd2463
Bump version: 0.1.9 → 0.1.10
Aug 30, 2025
076ecf9
Merge branch 'main' into dev
Dec 23, 2025
c10e9ab
pre-commit applied
Dec 23, 2025
c811523
patching
Dec 23, 2025
821bc7d
pre-commit errors managed
Dec 23, 2025
1ff2dac
pklm implementation validated
Dec 24, 2025
80e3d43
reformatted
Dec 24, 2025
a062588
merged
Dec 25, 2025
79c6ab4
test patched
Dec 25, 2025
99e58ae
doc improvement
Dec 25, 2025
26d25ac
mypy error patched
Dec 25, 2025
f22ec0d
out of bound int32 patched
Dec 25, 2025
4512e97
doc options robustified
Dec 25, 2025
f24b068
doc only running in latest python version
Dec 26, 2025
2f1cdc8
json doc bug patched
Dec 26, 2025
1b83c6d
Merge pull request #181 from scikit-learn-contrib/pklm-implementation
JulienRoussel77 Dec 26, 2025
561e587
tests updated
Dec 29, 2025
dc42bb5
typing and doc tests passed
Dec 29, 2025
a4014e1
commit uv lock
Dec 29, 2025
003a120
added temporary numpy version test
Dec 29, 2025
23ede5a
temporary numpy version test added
Dec 29, 2025
2b4775b
further test
Dec 30, 2025
5aaae49
lighter ci tests
Dec 30, 2025
23792e3
matrix output test replaced
Dec 30, 2025
2e5dcb6
removed randomness
Dec 30, 2025
3dd450e
doc tests made more robust
Jan 1, 2026
f525ecd
Merge pull request #182 from scikit-learn-contrib/feat/migration-uv
JulienRoussel77 Jan 1, 2026
4e7d6d6
Bump version: 0.1.10 → 0.2.0
Jan 1, 2026
584d951
History patched
Jan 1, 2026
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
2 changes: 1 addition & 1 deletion .bumpversion.cfg
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[bumpversion]
current_version = 0.1.9
current_version = 0.2.0
commit = True
tag = True

Expand Down
31 changes: 12 additions & 19 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,29 +4,22 @@ on:
release:
types: [published]

permissions:
id-token: write

jobs:
deploy:
runs-on: ubuntu-latest
environment: pypi

steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.10'
- name: Install Poetry
run: |
curl -sSL https://install.python-poetry.org | python3 -
echo "$HOME/.local/bin" >> $GITHUB_PATH
- name: Install dependencies
run: |
poetry install

- name: Install uv
uses: astral-sh/setup-uv@v3

- name: Build package
run: |
poetry build
- name: Publish package
env:
PYPI_TOKEN: ${{ secrets.PYPI_API_TOKEN }}
run: |
poetry config pypi-token.pypi $PYPI_TOKEN
poetry publish
run: uv build

- name: Publish to PyPI
uses: pypa/gh-action-pypi-publish@release/v1
77 changes: 29 additions & 48 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,58 +16,39 @@ jobs:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, windows-latest]
python-version: ["3.9", "3.11", "3.12"]
# Full matrix only for PRs to main
os: ${{ github.event_name == 'pull_request' && github.base_ref == 'main' && fromJSON('["ubuntu-latest", "windows-latest"]') || fromJSON('["ubuntu-latest"]') }}
python-version: ${{ github.event_name == 'pull_request' && github.base_ref == 'main' && fromJSON('["3.9", "3.11", "3.12"]') || fromJSON('["3.12"]') }}
defaults:
run:
shell: bash -l {0}

steps:
- name: Set OS and Python version
id: set-vars
run: |
if [[ "${GITHUB_REF}" == "refs/heads/main" || "${GITHUB_REF}" == "refs/heads/dev" ]]; then
echo "os-matrix=ubuntu-latest,windows-latest" >> $GITHUB_ENV
echo "python-matrix=3.9,3.11,3.12" >> $GITHUB_ENV
else
echo "os-matrix=ubuntu-latest" >> $GITHUB_ENV
echo "python-matrix=3.12" >> $GITHUB_ENV
fi
- name: Checkout
uses: actions/checkout@v3
- name: Python
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}
- name: Cache Poetry
uses: actions/cache@v3
with:
path: |
~/.cache/pypoetry
~/.cache/pip
key: ${{ runner.os }}-poetry-${{ matrix.python-version }}-${{ hashFiles('**/poetry.lock') }}
restore-keys: |
${{ runner.os }}-poetry-${{ matrix.python-version }}-
- name: Poetry
uses: snok/install-poetry@v1
- uses: actions/checkout@v4

- name: Install uv
uses: astral-sh/setup-uv@v3
with:
version: 1.8.3
- name: Lock
run: poetry lock --no-update
- name: Install
run: poetry install
- name: Checkers
run: make checkers
- name: Codecov
uses: codecov/codecov-action@v3
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
- name: Check Changed Files
id: changed-files
run: |
git fetch origin ${{ github.base_ref }}:${{ github.base_ref }} --depth=1
git diff --name-only ${{ github.base_ref }} > changed_files.txt
- name: Build Docs
if: contains(fromJSON('["docs/", ".rst"]').join(','), fromJSON('["${{ steps.changed-files.outputs.files }}"]').join(','))
enable-cache: true
cache-dependency-glob: "uv.lock"

- name: Set up Python ${{ matrix.python-version }}
run: uv python install ${{ matrix.python-version }}

- name: Install dependencies
run: make install

- name: Check with ruff
run: make check-quality

- name: Test with pytest
run: make check-tests

- name: Check types
run: make check-types

- name: Build and test docs
if: matrix.python-version == '3.12' && matrix.os == 'ubuntu-latest'
run: |
poetry run sphinx-build -b html docs/ _build/html
make doc
make doctest
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ var/
*.egg-info/
.installed.cfg
*.egg
poetry.lock

# PyInstaller
# Usually these files are written by a python script from a template
Expand Down
1 change: 0 additions & 1 deletion .python-version
Original file line number Diff line number Diff line change
@@ -1 +0,0 @@
env_qolmat_3.9
9 changes: 3 additions & 6 deletions CONTRIBUTING.rst
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,12 @@ Local setup

We encourage you to use a virtual environment. You'll want to activate it every time you want to work on `Qolmat`.

You can create a virtual environment via `conda`:
You can create a virtual environment and install dependencies with `uv`:

.. code:: sh

$ pip install poetry
$ poetry config virtualenvs.in-project true
$ poetry lock
$ poetry install
$ poetry shell
$ uv sync
$ uv run pytest

Once the environment is installed, pre-commit is installed, but need to be activated using the following command:

Expand Down
10 changes: 8 additions & 2 deletions HISTORY.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,18 @@
History
=======

0.1.10 (2024-??-??)
0.2.0 (2026-01-01)
------------------
* PLKM test implemented and documented in the holes_characterization module
* Dependency management improved with uv
* Migrated from hyperopt to skopt for hyperparameter optimization

0.1.10 (2025-08-30)
------------------
* Long EM and RPCA operations wrapped with tqdm progress bars
* Readme code sample updated, and results table made consistent

0.1.9 (2024-08-29)
0.1.9 (2025-08-29)
------------------
* Tutorials reproducibility improved with random_state parameters
* RPCA now accepts random_state parameters
Expand Down
41 changes: 26 additions & 15 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,34 +1,45 @@
# Install dependencies
install:
uv sync --all-extras

# Code quality checks
check-coverage:
poetry run pytest --cov-branch --cov=qolmat/ --cov-report=xml tests/

check-poetry:
poetry check --lock
uv run pytest --cov-branch --cov=qolmat/ --cov-report=xml tests/

check-quality:
poetry run ruff check qolmat/ tests/
uv run ruff check qolmat/ tests/

check-security:
poetry run bandit --recursive --configfile=pyproject.toml qolmat/
uv run bandit --recursive --configfile=pyproject.toml qolmat/

check-tests:
poetry run pytest tests/
uv run pytest tests/

check-types:
poetry run mypy qolmat/ tests/
uv run mypy qolmat/ tests/

checkers: check-coverage check-types

# Formatting
format:
uv run ruff format qolmat/ tests/
uv run ruff check --fix qolmat/ tests/

# Cleaning
clean:
rm -rf .mypy_cache .pytest_cache .coverage*
rm -rf .mypy_cache .pytest_cache .coverage* .ruff_cache
rm -rf **__pycache__
make clean -C docs

coverage:
poetry run pytest --cov-branch --cov=qolmat --cov-report=xml tests
uv run make clean -C docs

# Documentation
doc:
make html -C docs
uv run make html -C docs

doctest:
poetry run pytest --doctest-modules --pyargs qolmat
uv run pytest --doctest-modules --pyargs qolmat

# Development helpers
lock:
uv lock

.PHONY: install check-coverage check-quality check-security check-tests check-types checkers format clean doc doctest lock
10 changes: 5 additions & 5 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
author = "Quantmetry"

# The full version, including alpha/beta/rc tags
version = "0.1.9"
version = "0.2.0"
release = version

# -- General configuration ---------------------------------------------------
Expand All @@ -53,8 +53,6 @@
# see https://github.com/numpy/numpydoc/issues/69
numpydoc_show_class_members = False

from distutils.version import LooseVersion

# pngmath / imgmath compatibility layer for different sphinx versions
# import sphinx

Expand All @@ -75,7 +73,7 @@
source_suffix = ".rst"

# Generate the plots for the gallery
plot_gallery = True
plot_gallery = "True"

# The master toctree document.
master_doc = "index"
Expand Down Expand Up @@ -156,9 +154,11 @@
"gallery_dirs": ["examples/tutorials/"],
"doc_module": "qolmat",
"backreferences_dir": os.path.join("generated"),
"reference_url": {"qolmat": None},
"reference_url": {},
"inspect_global_variables": False,
}


suppress_warnings = ["autosectionlabel.*"]

# doctest configuration
Expand Down
52 changes: 52 additions & 0 deletions docs/sg_execution_times.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@

:orphan:

.. _sphx_glr_sg_execution_times:


Computation times
=================
**01:04.897** total execution time for 6 files **from all galleries**:

.. container::

.. raw:: html

<style scoped>
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/5.3.0/css/bootstrap.min.css" rel="stylesheet" />
<link href="https://cdn.datatables.net/1.13.6/css/dataTables.bootstrap5.min.css" rel="stylesheet" />
</style>
<script src="https://code.jquery.com/jquery-3.7.0.js"></script>
<script src="https://cdn.datatables.net/1.13.6/js/jquery.dataTables.min.js"></script>
<script src="https://cdn.datatables.net/1.13.6/js/dataTables.bootstrap5.min.js"></script>
<script type="text/javascript" class="init">
$(document).ready( function () {
$('table.sg-datatable').DataTable({order: [[1, 'desc']]});
} );
</script>

.. list-table::
:header-rows: 1
:class: table table-striped sg-datatable

* - Example
- Time
- Mem (MB)
* - :ref:`sphx_glr_examples_tutorials_plot_tuto_benchmark_TS.py` (``../examples/tutorials/plot_tuto_benchmark_TS.py``)
- 00:21.381
- 0.0
* - :ref:`sphx_glr_examples_tutorials_plot_tuto_categorical.py` (``../examples/tutorials/plot_tuto_categorical.py``)
- 00:16.026
- 0.0
* - :ref:`sphx_glr_examples_tutorials_plot_tuto_diffusion_models.py` (``../examples/tutorials/plot_tuto_diffusion_models.py``)
- 00:11.896
- 0.0
* - :ref:`sphx_glr_examples_tutorials_plot_tuto_mcar.py` (``../examples/tutorials/plot_tuto_mcar.py``)
- 00:08.072
- 0.0
* - :ref:`sphx_glr_examples_tutorials_plot_tuto_mean_median.py` (``../examples/tutorials/plot_tuto_mean_median.py``)
- 00:04.939
- 0.0
* - :ref:`sphx_glr_examples_tutorials_plot_tuto_hole_generator.py` (``../examples/tutorials/plot_tuto_hole_generator.py``)
- 00:02.583
- 0.0
18 changes: 8 additions & 10 deletions examples/benchmark.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,7 @@ First, import some useful libraries
```python tags=[]
import warnings
# warnings.filterwarnings('error')
```

```python tags=[]
%reload_ext autoreload
%autoreload 2

Expand All @@ -33,21 +31,21 @@ from IPython.display import Image
import pandas as pd
from datetime import datetime
import numpy as np
import hyperopt as ho
from skopt.space import Real, Integer, Categorical
np.random.seed(1234)
from matplotlib import pyplot as plt
import matplotlib.ticker as plticker

tab10 = plt.get_cmap("tab10")
plt.rcParams.update({'font.size': 18})


from sklearn.linear_model import LinearRegression

from qolmat.benchmark import comparator, missing_patterns
from qolmat.imputations import imputers
from qolmat.utils import data, utils, plot


```

### **I. Load data**
Expand Down Expand Up @@ -124,15 +122,15 @@ imputer_residuals = imputers.ImputerResiduals(groups=("station",), period=365, m
imputer_rpca = imputers.ImputerRpcaNoisy(groups=("station",), columnwise=False, max_iterations=500, tau=.01, lam=5, rank=1)
imputer_rpca_opti = imputers.ImputerRpcaNoisy(groups=("station",), columnwise=False, max_iterations=256)
dict_config_opti["RPCA_opti"] = {
"tau": ho.hp.uniform("tau", low=.5, high=5),
"lam": ho.hp.uniform("lam", low=.1, high=1),
"tau": Real(0.5, 5.0, name="tau"),
"lam": Real(0.1, 1.0, name="lam"),
}
imputer_rpca_opticw = imputers.ImputerRpcaNoisy(groups=("station",), columnwise=False, max_iterations=256)
dict_config_opti["RPCA_opticw"] = {
"tau/TEMP": ho.hp.uniform("tau/TEMP", low=.5, high=5),
"tau/PRES": ho.hp.uniform("tau/PRES", low=.5, high=5),
"lam/TEMP": ho.hp.uniform("lam/TEMP", low=.1, high=1),
"lam/PRES": ho.hp.uniform("lam/PRES", low=.1, high=1),
"tau/TEMP": Real(0.5, 5.0, name="tau/TEMP"),
"tau/PRES": Real(0.5, 5.0, name="tau/PRES"),
"lam/TEMP": Real(0.1, 1.0, name="lam/TEMP"),
"lam/PRES": Real(0.1, 1.0, name="lam/PRES"),
}

imputer_normal_sample = imputers.ImputerEM(groups=("station",), model="multinormal", method="sample", max_iter_em=8, n_iter_ou=128, dt=4e-2)
Expand Down
Loading
Loading