From 2571bd621ce7d6cc476c57693c974d260c1c3cb9 Mon Sep 17 00:00:00 2001 From: Aaron Meyer Date: Fri, 21 Aug 2026 09:00:04 -0700 Subject: [PATCH] Fix figure build failures (M2, M3, M4, MS7) - Move the fancyimpute/scikit-learn check_array compat patch from clustering.py into ddmc/__init__.py, which always runs before any submodule's own imports. figureM2.py imported fancyimpute before ..clustering, so the patch was applied too late and IterativeSVD crashed with TypeError: unexpected keyword 'force_all_finite'. - Fix get_pssms(clusters=...) misuse in figureM3.py/figureMS7.py: both stripped the cluster axis with a trailing [0], causing plot_cluster_kinase_distances to silently pick the wrong phosphoacceptor and then crash with an out-of-bounds IndexError. Correct the corresponding indexing in common.py to select down the position-5 column across amino acids. - Coerce X/y to ndarrays in plot_roc so positional CV-fold indexing works regardless of whether the caller passes a pandas Series with a non-integer index (figureM4 crashed with a pandas KeyError under newer pandas). Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_014sHWCv3yz7DGDVDKra9KUo --- ddmc/__init__.py | 17 +++++++++++++++++ ddmc/clustering.py | 19 +------------------ ddmc/figures/common.py | 2 +- ddmc/figures/figureM3.py | 2 +- ddmc/figures/figureMS7.py | 2 +- ddmc/logistic_regression.py | 2 ++ 6 files changed, 23 insertions(+), 21 deletions(-) diff --git a/ddmc/__init__.py b/ddmc/__init__.py index c4a96af4..b52ad464 100644 --- a/ddmc/__init__.py +++ b/ddmc/__init__.py @@ -1,3 +1,20 @@ """This is the __init__.py file.""" +import sklearn.utils + __version__ = "0.0.1" + +# fancyimpute (unmaintained since 2020) calls check_array with the +# `force_all_finite` kwarg, which scikit-learn renamed to `ensure_all_finite` +# and later removed. Patch it here, at package-import time, so it is in place +# before any submodule (however it orders its own imports) pulls in fancyimpute. +_sklearn_check_array = sklearn.utils.check_array + + +def _check_array_compat(X, **kwargs): + if "force_all_finite" in kwargs: + kwargs["ensure_all_finite"] = kwargs.pop("force_all_finite") + return _sklearn_check_array(X, **kwargs) + + +sklearn.utils.check_array = _check_array_compat # ty: ignore[invalid-assignment] diff --git a/ddmc/clustering.py b/ddmc/clustering.py index d936a85f..012b403a 100644 --- a/ddmc/clustering.py +++ b/ddmc/clustering.py @@ -6,7 +6,7 @@ import numpy as np import pandas as pd -import sklearn.utils +from fancyimpute import SoftImpute from sklearn.mixture import GaussianMixture from sklearn.utils.validation import check_is_fitted @@ -14,23 +14,6 @@ from .motifs import compute_control_pssm, get_pspls from .pam250 import PAM250 -# fancyimpute (unmaintained since 2020) calls check_array with the -# `force_all_finite` kwarg, which scikit-learn renamed to `ensure_all_finite` -# and later removed. Patch it before fancyimpute's submodules import -# check_array into their own namespaces, rather than forking fancyimpute. -_sklearn_check_array = sklearn.utils.check_array - - -def _check_array_compat(X, **kwargs): - if "force_all_finite" in kwargs: - kwargs["ensure_all_finite"] = kwargs.pop("force_all_finite") - return _sklearn_check_array(X, **kwargs) - - -sklearn.utils.check_array = _check_array_compat # ty: ignore[invalid-assignment] - -from fancyimpute import SoftImpute # noqa: E402 - class DDMC(GaussianMixture): """Cluster peptides by both sequence similarity and condition-wise phosphorylation following an diff --git a/ddmc/figures/common.py b/ddmc/figures/common.py index e0933049..14dcbd8d 100644 --- a/ddmc/figures/common.py +++ b/ddmc/figures/common.py @@ -191,7 +191,7 @@ def plot_cluster_kinase_distances( KinToPhosphotypeDict[kin] for kin in distances_pssm["Kinase"] ] try: - most_frequent_phosphoacceptor = AAlist[pssms[i, 5].argmax()] + most_frequent_phosphoacceptor = AAlist[int(np.argmax(pssms[i, :, 5]))] except Exception: most_frequent_phosphoacceptor = "S/T" if most_frequent_phosphoacceptor == "S" or most_frequent_phosphoacceptor == "T": diff --git a/ddmc/figures/figureM3.py b/ddmc/figures/figureM3.py index b896e7fb..71398d8d 100644 --- a/ddmc/figures/figureM3.py +++ b/ddmc/figures/figureM3.py @@ -84,7 +84,7 @@ def plot_fig_3abd(ax_a, ax_b, ax_d): # Plot kinase predictions for cluster 16 plot_cluster_kinase_distances( model.predict_upstream_kinases()[[16]], - model.get_pssms(PsP_background=True, clusters=[16])[0], + model.get_pssms(PsP_background=True, clusters=[16]), ax=ax_d, ) diff --git a/ddmc/figures/figureMS7.py b/ddmc/figures/figureMS7.py index 9fa51d0f..afbb008b 100644 --- a/ddmc/figures/figureMS7.py +++ b/ddmc/figures/figureMS7.py @@ -54,7 +54,7 @@ def makeFigure(): plot_cluster_kinase_distances( model.predict_upstream_kinases()[top_clusters], - model.get_pssms(PsP_background=True, clusters=top_clusters)[0], + model.get_pssms(PsP_background=True, clusters=top_clusters), ax=axes[3], ) return f diff --git a/ddmc/logistic_regression.py b/ddmc/logistic_regression.py index 3a4f0056..0a928f64 100644 --- a/ddmc/logistic_regression.py +++ b/ddmc/logistic_regression.py @@ -62,6 +62,8 @@ def plot_roc( ax: Axes | None = None, ): """Plot Receiver Operating Characteristc with cross-validation folds of a given classifier model.""" + X = np.asarray(X) + y = np.asarray(y) if kfold == "Stratified": cv = StratifiedKFold(n_splits=cv_folds) elif kfold == "Repeated":