Skip to content
Open
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
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ build-backend = "hatchling.build"

[project]
name = "scorepilot"
version = "0.22.0"
version = "0.22.1"
description = "Web-based tool for PCA/PLS model analysis in chemometrics."
readme = "README.md"
requires-python = ">=3.12"
Expand Down
9 changes: 5 additions & 4 deletions src/scorepilot/api/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -334,7 +334,8 @@ def get_model(
"""Return a model's Logbook: metadata, recipe, lineage, and diagnostics.

Diagnostics are recomputed from the source dataset and stored spec. If the
dataset is no longer in memory, the entry is returned without diagnostics.
dataset is no longer available (the source dataset record is missing or
deleted), the entry is returned without diagnostics.

``n_components`` previews the diagnostics at a different component count
without persisting it - this backs the live component explorer, which scrubs
Expand Down Expand Up @@ -383,7 +384,7 @@ def update_model(
if dataset is None:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="Source dataset is no longer loaded; cannot refit.",
detail="Source dataset is no longer available; cannot refit.",
)

spec = PreprocessingSpec.from_dict(model.preprocessing)
Expand Down Expand Up @@ -424,7 +425,7 @@ def model_contributions(
if dataset is None:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="Source dataset is no longer loaded; cannot compute contributions.",
detail="Source dataset is no longer available; cannot compute contributions.",
)

spec = PreprocessingSpec.from_dict(model.preprocessing)
Expand Down Expand Up @@ -486,7 +487,7 @@ def model_cross_validation(
if dataset is None:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="Source dataset is no longer loaded; cannot cross-validate.",
detail="Source dataset is no longer available; cannot cross-validate.",
)

ceiling = min(max_components or model.n_components, _AUTO_MAX_COMPONENTS)
Expand Down
5 changes: 3 additions & 2 deletions src/scorepilot/core/profiling.py
Original file line number Diff line number Diff line change
Expand Up @@ -143,8 +143,9 @@ def suggest_transform(summary: VariableSummary) -> TransformKind:
"""Suggest a transform from a variable's shape.

A strongly right-skewed, strictly positive variable with a wide dynamic range
is a candidate for a log transform; a milder skew suggests a signed power
(root). Otherwise no transform is suggested.
is a candidate for a log transform; a strong skew that isn't positive with a
wide dynamic range suggests a signed power (root). Otherwise no transform is
suggested.
"""
if summary.column_type is not ColumnType.QUANTITATIVE or summary.skewness is None:
return TransformKind.NONE
Expand Down
4 changes: 3 additions & 1 deletion src/scorepilot/core/transforms.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,9 @@ def apply_transform(
- ``neglog``: ``sign(x) * log1p(abs(x))`` (sign-symmetric log)
- ``logit``: ``log(p / (1 - p))`` with ``p = x`` (defined for ``0 < x < 1``)
- ``exponential``: ``exp(x)``
- ``power``: ``sign(x) * abs(x) ** c1`` (default ``c1 = 0.5``, i.e. signed root)
- ``power``: ``sign(x) * abs(x) ** c1``. The parameter default is
``c1=0.0``, which ``_transform_values`` remaps internally to ``0.5``
(signed root); pass a non-zero ``c1`` to use it directly.
"""
values = to_numeric(series).astype(float).to_numpy()

Expand Down
9 changes: 5 additions & 4 deletions src/scorepilot/db/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,11 @@ def __repr__(self) -> str:
class Model(Base):
"""A fitted PCA/PLS model variant.

Queryable metadata lives in real columns and JSON; the fitted arrays (P, W,
means, scales, ...) are stored as a compressed ``npz`` blob in ``params``. If
those artifacts grow, ``params`` can be swapped for an object-storage path
behind the same repository method without changing anything upstream.
Queryable metadata lives in real columns and JSON; the fitted arrays
(``x_loadings``, ``explained_variance``, ``r2_cumulative``) are stored as a
compressed ``npz`` blob in ``params``. If those artifacts grow, ``params``
can be swapped for an object-storage path behind the same repository method
without changing anything upstream.
"""

__tablename__ = "model"
Expand Down
5 changes: 3 additions & 2 deletions src/scorepilot/schemas.py
Original file line number Diff line number Diff line change
Expand Up @@ -302,8 +302,9 @@ class FitModelRequest(ApiModel):

With ``auto_components`` the number of components is chosen by
cross-validation via the selected ``selection_rule`` (the one-standard-error
rule for PLS and the lowest cross-validated error for PCA, by default), and
``n_components`` is used only as an upper bound on what is evaluated.
rule for PLS and the lowest cross-validated error for PCA, by default).
When ``auto_components`` is set, the request's ``n_components`` is ignored;
cross-validation evaluates up to a fixed internal ceiling.
"""

dataset_id: str
Expand Down
Loading