Skip to content
Merged
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
52 changes: 30 additions & 22 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,35 +8,43 @@ and this project adheres to

## [4.3.0] - 2026-09-02

### Changed
### Added

- `deeplc.calibration` is now a package. `deeplc.calibration.simple` holds the naive,
single-series calibrations unchanged (`Calibration` ABC, `IdentityCalibration`,
`PiecewiseLinearCalibration`, `SplineTransformerCalibration`). New
`deeplc.calibration.multihead` holds `MultiHeadCalibration`, the ABC for a calibration that
takes the whole `(n, n_heads)` prediction matrix `predict(..., return_matrix=True)` returns and
selects its own head(s): `MultiHeadPiecewiseLinearCalibration` and `MultiHeadSplineCalibration`
rank heads by Pearson correlation and delegate to the matching naive class on the winner, and
`MultiHeadRidgeCalibration` combines several best-correlating heads with a ridge fit. All three
are re-exported from `deeplc.calibration`, unchanged import path for existing names.

- Calibration of a multitask model now combines several LC-setup heads instead of keeping only
the best-correlating one. `calibrate` and `predict_and_calibrate` default to the new
`MultiHeadRidgeCalibration`: heads are ranked by Pearson correlation to the reference as
before, the 80 best are each calibrated with `SplineTransformerCalibration`, and a ridge
regression maps the calibrated estimates onto the observed retention times.
On the eight PRIDE setups that no DeepLC model was trained on, `MultiHeadRidgeCalibration`
lowered the held-out error on all eight, by a median of 13 % relative to the observed gradient.

On the eight PRIDE setups that no DeepLC model was trained on this lowered the held-out error
on all eight, by a median of 13 % relative to the observed gradient (0.01248 to 0.01090
MAE/span). Fitting is faster than the previous path because the head ranking is vectorised
(median 1.0 s against 2.3 s), and prediction is unchanged since the full head matrix is
computed either way.
- `deeplc.calibration.upgrade_calibration`, wrapping an unfitted naive `Calibration` in its
`MultiHead*Calibration` counterpart. `calibrate()` and `predict_and_calibrate()` call it on
whatever `calibration` they are given, so passing a naive instance (e.g.
`SplineTransformerCalibration()`) still works, calibrated on the best-correlating head instead
of head 0. A fitted naive instance is rejected: it carries no record of which head it was fit
on, so fit a `MultiHead*Calibration` instead in that case.

Single-task models keep the previous default (`SplineTransformerCalibration`), and passing
a calibration instance restores the old behaviour on any model:
### Changed

```python
from deeplc import predict_and_calibrate
from deeplc.calibration import SplineTransformerCalibration
- `calibrate()` and `predict_and_calibrate()` default to `MultiHeadRidgeCalibration()` for every
model, single-task included (it reduces to a spline plus a linear rescaling on one column). Pass
`MultiHeadSplineCalibration()` or `MultiHeadPiecewiseLinearCalibration()` for a lighter
calibration. `Calibration.selected_model_head`/`uses_all_heads` are gone: head selection now
lives entirely in the `MultiHeadCalibration` implementations.

rt = predict_and_calibrate(psms, psm_list_reference=reference,
calibration=SplineTransformerCalibration())
```
**Breaking**: an already-fitted naive `Calibration` passed directly to
`predict_and_calibrate()` is now rejected; fit a `MultiHead*Calibration` instead.

### Added
### Fixed

- `Calibration.uses_all_heads`, telling `calibrate` and `predict_and_calibrate` to hand a
calibration the whole `(n, n_heads)` prediction matrix rather than a single column.
- `IdentityCalibration()` could not be instantiated: it never overrode the abstract
`Calibration.__init__`.

## [4.2.0] - 2026-08-28

Expand Down
42 changes: 42 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,48 @@ If you have an idea for a feature, use case to add or an approach for a bugfix,
it is best to communicate with the community by creating an issue in
[GitHub issues](https://github.com/compomics/DeepLC/issues).

## Codebase overview

DeepLC predicts peptide retention times using a 1D-CNN model trained on atomic composition
features.

- **Feature extraction** (`deeplc/_features.py`) — `encode_peptidoform()` converts a ProForma
peptidoform string into per-position atomic composition arrays (C, H, N, O, S, P) plus a 20-AA
one-hot encoding. Padding to 60 residues. Uses `psm_utils.Peptidoform` as the canonical peptide
representation.
- **Dataset** (`deeplc/data.py`) — `DeepLCDataset` wraps lists of `Peptidoform` objects into a
PyTorch `Dataset`. Features are encoded lazily in `__getitem__`. `split_datasets()` handles
train/validation splits.
- **Model architecture** (`deeplc/_architecture.py`) — `DeepLCModel`: Conv1D branches (atomic,
summed-atomic, global, one-hot) feed a shared dense trunk into `BatchedHeads` returning
`[batch, n_heads]`. An optional fine-tuning adapter (`self.adapter`, attached via
`add_adapter()`) maps head output to `[batch, 1]`.
- **Training/inference** (`deeplc/_model_ops.py`) — `load_model()`, `train()`, `predict()`,
`evaluate()`. Checkpoints are plain state dicts loaded with `weights_only=True`.
- **Calibration** (`deeplc/calibration/` package) — `predict(..., return_matrix=True)` always
returns a `(n, n_heads)` matrix, `n_heads=1` for a single-setup model.
`deeplc/calibration/simple.py` holds naive, single-series calibrations (`Calibration` ABC,
`IdentityCalibration`, `PiecewiseLinearCalibration`, `SplineTransformerCalibration`) that map
one column onto observed RT space and know nothing about heads.
`deeplc/calibration/multihead.py` holds `MultiHeadCalibration` ABC and the classes that pick
their own head(s) from the matrix: `MultiHeadPiecewiseLinearCalibration` and
`MultiHeadSplineCalibration` (rank heads by correlation, delegate to the matching `simple.py`
class) and `MultiHeadRidgeCalibration` (combines the best-correlating heads with a ridge fit).
`core.calibrate()`/`predict_and_calibrate()` only accept `MultiHeadCalibration` instances and
always hand over the full matrix; the default is `MultiHeadRidgeCalibration`.
- **Reference selection** (`deeplc/_reference_selection.py`) — selects high-confidence PSMs from
input for auto-calibration.
- **Core API** (`deeplc/core.py`) — top-level functions: `predict()`, `calibrate()`,
`predict_and_calibrate()`, `finetune_and_predict()`.
- **CLI** (`deeplc/__main__.py`) — two subcommands, `predict` and `gui`. Reads PSM files via
`psm_utils.io.read_file()`.
- **GUI** (`deeplc/gui.py`) — NiceGUI-based web UI, launchable as browser app or native desktop
window via `pywebview`.

Conventions: peptide sequences use ProForma notation throughout (via `psm_utils.Peptidoform`);
PSM collections are `psm_utils.PSMList`; line length is 99 characters (ruff); Python >= 3.11 with
`from __future__ import annotations`.

## How to contribute

- Fork [DeepLC](https://github.com/compomics/DeepLC) on GitHub to
Expand Down
29 changes: 29 additions & 0 deletions deeplc/calibration/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
"""Calibration utilities."""

from deeplc.calibration.multihead import (
MultiHeadCalibration,
MultiHeadPiecewiseLinearCalibration,
MultiHeadRidgeCalibration,
MultiHeadSplineCalibration,
upgrade_calibration,
)
from deeplc.calibration.simple import (
Calibration,
IdentityCalibration,
PiecewiseLinearCalibration,
SplineTransformerCalibration,
)
from deeplc.exceptions import CalibrationError

__all__ = [
"Calibration",
"CalibrationError",
"IdentityCalibration",
"MultiHeadCalibration",
"MultiHeadPiecewiseLinearCalibration",
"MultiHeadRidgeCalibration",
"MultiHeadSplineCalibration",
"PiecewiseLinearCalibration",
"SplineTransformerCalibration",
"upgrade_calibration",
]
Loading
Loading