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
15 changes: 13 additions & 2 deletions packages/imspy-predictors/src/imspy_predictors/pretrained/hub.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,9 @@
)

# Maps the *package-relative* path (as used by callers of get_model_path)
# to its download URL and expected SHA-256 hash.
# to its download URL and expected SHA-256 hash. Entries default to the
# rustims models GitHub Release; an explicit "url" overrides that for
# vendor-free upstream redistributions (e.g. Chronologer).
MODELS = {
"ccs/best_model.pt": {
"filename": "ccs-best_model.pt",
Expand All @@ -51,6 +53,15 @@
"filename": "pretrained_encoder.pt",
"sha256": "43ccc2f836bf3d81943ddce353ade9628e7d036421ba5b5c182bf163e496385e",
},
# Chronologer base weights — fetched directly from upstream Searle Lab
# (Apache-2.0, attribution preserved in imspy_predictors.rt.chronologer).
# We deliberately do not re-host: pulls from the upstream repo so any
# future fix or retraining propagates automatically.
"rt/chronologer_base.pt": {
"filename": "chronologer_base.pt",
"url": "https://github.com/searlelab/chronologer/raw/main/models/Chronologer_20220601193755.pt",
"sha256": "1a500c246b49a1a23643bce7f2df86d5a107359bf0ec34365531c73431b6c0b3",
},
}


Expand Down Expand Up @@ -153,7 +164,7 @@ def ensure_model(model_name: str) -> Path:

# 3. Download into a temp file in the same filesystem, then atomic-rename.
cached_path.parent.mkdir(parents=True, exist_ok=True)
url = f"{_RELEASE_BASE}/{meta['filename']}"
url = meta.get("url") or f"{_RELEASE_BASE}/{meta['filename']}"
logger.info("Downloading model '%s' from %s ...", model_name, url)

tmp_fd, tmp_path = tempfile.mkstemp(
Expand Down
31 changes: 29 additions & 2 deletions packages/imspy-predictors/src/imspy_predictors/rt/predictors.py
Original file line number Diff line number Diff line change
Expand Up @@ -228,18 +228,45 @@ def load_deep_retention_time_predictor(backend: Optional[str] = None):
"""
Load a pretrained retention time predictor model.

Defaults to **Chronologer** (Searle Lab, Apache-2.0) — a residual-CNN that
reaches roughly 4× tighter median residual than the imspy transformer
baseline on timsTOF data. Pass ``backend="transformer"`` to opt back into
the legacy imspy ``UnifiedPeptideModel`` RT predictor.

Args:
backend: Kept for backward compatibility, ignored (always uses PyTorch)
backend: ``"chronologer"`` (default, or pass ``None``) loads the
Chronologer wrapper. ``"transformer"`` loads the legacy imspy
transformer RT model. Any other value is treated as the default.

Returns:
Loaded PyTorch model
Either a :class:`Chronologer` wrapper or the legacy transformer
PyTorch model, depending on ``backend``.
"""
if not TORCH_AVAILABLE:
raise ImportError(
"PyTorch is required for retention time prediction. "
"Install with: pip install torch"
)

backend = (backend or "chronologer").lower()

if backend == "chronologer":
# Default: Chronologer is the goto RT predictor on timsTOF data.
# Falls back to the transformer path only if Chronologer can't be
# constructed (e.g. upstream `chronologer` package not installed, or
# the base-weights download is unreachable).
try:
from imspy_predictors.rt.chronologer import Chronologer
base_path = get_model_path('rt/chronologer_base.pt')
return Chronologer.from_base(str(base_path))
except (ImportError, FileNotFoundError, RuntimeError) as e:
import logging
logging.getLogger(__name__).warning(
"Chronologer load failed (%s); falling back to transformer.", e,
)
backend = "transformer"

# Transformer path (legacy / fallback).
# Try to load UnifiedPeptideModel first (new architecture)
try:
from imspy_predictors.models import UnifiedPeptideModel
Expand Down
Loading