Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
a593863
fix rm missing
marouenbg Feb 16, 2022
443fcdd
Merge remote-tracking branch 'upstream/devel' into devel
marouenbg Feb 18, 2022
c70f7aa
Merge remote-tracking branch 'upstream/devel' into devel
marouenbg Jul 7, 2022
4a84fc7
Merge remote-tracking branch 'upstream/devel' into devel
marouenbg Jul 27, 2022
3cad3d7
Merge remote-tracking branch 'upstream/devel' into devel
marouenbg Jul 29, 2022
45925b5
Merge remote-tracking branch 'upstream/devel' into devel
marouenbg Oct 5, 2022
bf7bf4b
Merge remote-tracking branch 'upstream/devel' into devel
marouenbg Oct 27, 2022
b3a8c73
Merge remote-tracking branch 'upstream/devel' into devel
marouenbg Nov 25, 2022
2cd6073
Merge remote-tracking branch 'upstream/devel' into devel
marouenbg Jan 10, 2023
4ec8665
Merge remote-tracking branch 'upstream/devel' into devel
marouenbg Nov 11, 2023
a77880a
Merge remote-tracking branch 'upstream/devel' into devel
marouenbg Oct 5, 2025
4ddf510
cobra hotfix
marouenbg Oct 5, 2025
27bf7c3
cobra hotfix
marouenbg Oct 5, 2025
8096812
cobra hotfix
marouenbg Oct 5, 2025
f1145b6
cobra hotfix
marouenbg Oct 5, 2025
01cde28
add transpose of psi
marouenbg Oct 5, 2025
8cb7d04
Fix assignment operator for Lasso model
marouenbg Mar 25, 2026
9a540a4
Merge branch 'devel' into fix-cobra
marouenbg Mar 25, 2026
3204813
Refine parameter description and update model fitting
marouenbg Mar 25, 2026
124fda5
Fix pandas indexing in cobra test: convert X to numpy before mean
marouenbg Apr 1, 2026
db762d9
Fix pandas/numpy compat in condor: use iloc and np.asarray for sum
marouenbg Apr 1, 2026
1dab8fe
Rename cobra 'deprecated' mode to 'MLE' and populate alpha param docs
marouenbg Apr 1, 2026
bc3ca8f
Add mode parameter to cobra: 'corr' (default) or 'cov' for covariance…
marouenbg Apr 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
66 changes: 45 additions & 21 deletions netZooPy/cobra/cobra.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import pandas as pd
import numpy as np
from scipy.linalg import eigh,pinv
from sklearn.linear_model import LinearRegression, Lasso


def cobra(X, expression):
def cobra(X, expression, cobra='nnls', alpha: np.float64=0.1, mode='corr'):
"""
COBRA decomposes a (partial) gene co-expression matrix as a
linear combination of covariate-specific components.
Expand All @@ -13,9 +14,21 @@ def cobra(X, expression):
Parameters
-----------
X : np.ndarray, pd.DataFrame
design matrix of size (n, q), n = number of samples, q = number of covariates
design matrix of size (n, q), n = number of samples, q = number of covariates.
Please add an intercept column in X (first column made of ones).
expression : np.ndarray, pd.DataFrame
gene expression as a matrix of size (g, n), g = number of genes
cobra : string
regression mode
nnls: Non-negative least square (default)
nnlasso: Non-negative LASSO
MLE: Maximum likelihood estimation
alpha : np.float64
Regularization parameter for the LASSO model (default 0.1). Only used when cobra='nnlasso'.
mode : string
Type of matrix to decompose.
corr: Correlation matrix (default). Gene expressions are centered and normalized to unit norm.
cov: Covariance matrix. Gene expressions are centered and divided by sqrt(n-1).
Returns
---------
psi : array
Expand Down Expand Up @@ -43,8 +56,13 @@ def cobra(X, expression):
_, q = X.shape

# Standardize Gene Expressions
g = expression - expression.mean(axis=1).reshape(-1, 1)
g = g / np.linalg.norm(g, axis=1)[:, None]
g = expression - expression.mean(axis=1).reshape(-1, 1)
if mode == 'corr':
g = g / np.linalg.norm(g, axis=1)[:, None]
elif mode == 'cov':
g = g / np.sqrt(n - 1)
else:
raise ValueError("mode must be 'corr' or 'cov'.")

# Co-expression Matrix
c = np.dot(g, g.T)
Expand All @@ -55,26 +73,32 @@ def cobra(X, expression):
Q = c_eigenvectors[:, indices_nonzero].T[::-1].T

#
gtq = np.matmul(g.T, Q)
d = c_eigenvalues[indices_nonzero][::-1]

#
xtx_inv = np.linalg.pinv(
np.dot(X.T, X)
)
xtx_inv_xt = np.dot(
xtx_inv, X.T
)
if cobra=='nnls':
model = LinearRegression(positive=True, fit_intercept=False).fit(X, np.diag(d) )
psi = np.transpose(model.coef_)
elif cobra=='nnlasso':
model = Lasso(alpha=alpha, positive=True, fit_intercept=False).fit(X, np.diag(d) )
psi = np.transpose(model.coef_)
elif cobra=='MLE':
gtq = np.matmul(g.T, Q)
xtx_inv = np.linalg.pinv(
np.dot(X.T, X)
)
xtx_inv_xt = np.dot(
xtx_inv, X.T
)

#
psi = np.zeros((q, n))
#
psi = np.zeros((q, n))

for i in range(q):
for h in range(n):
psi[i, h] = n * np.sum([
(
xtx_inv_xt[i, k] * gtq[k, h] ** 2
) for k in range(n)
])
for i in range(q):
for h in range(n):
psi[i, h] = n * np.sum([
(
xtx_inv_xt[i, k] * gtq[k, h] ** 2
) for k in range(n)
])

return psi, Q, d, g
4 changes: 2 additions & 2 deletions netZooPy/condor/condor.py
Original file line number Diff line number Diff line change
Expand Up @@ -305,13 +305,13 @@ def matrices(self, c,resolution):
# Computes weighted biadjacency matrix.
A = np.matrix(np.zeros((p, q)))
for edge in self.net.iterrows():
A[gn[edge[1][1]], rg[edge[1][0]]] = edge[1][2]
A[gn[edge[1].iloc[1]], rg[edge[1].iloc[0]]] = edge[1].iloc[2]

# Computes node degrees for the nodesets.
ki = A.sum(1)
dj = A.sum(0)
# Computes sum of edges and bimodularity matrix.
m = float(sum(ki))
m = float(np.asarray(ki).sum())
B = A - resolution*((ki @ dj) / m)

# d = self.index_dict
Expand Down
3 changes: 2 additions & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@ igraph
joblib
statsmodels
click
torch
scikit-learn
torch
7 changes: 4 additions & 3 deletions tests/test_cobra.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ def test_cobra():
G_gt = pd.read_csv(G_gt_path, index_col=0)

# Call COBRA
psi, Q, D, G = cobra.cobra(X, expression)
psi, Q, D, G = cobra.cobra(X, expression, cobra='MLE')

# Cast output to pandas
psi = pd.DataFrame(psi, index=psi_gt.index, columns=psi_gt.columns)
Expand All @@ -37,7 +37,8 @@ def test_cobra():
pd.testing.assert_frame_equal(G, G_gt, rtol=1e-10, check_exact=False)

q = psi.shape[0]
X_mean = np.mean(X.to_numpy(), axis=0)
for i in range(q):
C = Q.to_numpy().dot(np.mean(X, axis=0)[i] * np.diag(psi.to_numpy()[i, :])).dot(Q.to_numpy().T)
C_gt = Q_gt.to_numpy().dot(np.mean(X, axis=0)[i] * np.diag(psi_gt.to_numpy()[i, :])).dot(Q_gt.to_numpy().T)
C = Q.to_numpy().dot(X_mean[i] * np.diag(psi.to_numpy()[i, :])).dot(Q.to_numpy().T)
C_gt = Q_gt.to_numpy().dot(X_mean[i] * np.diag(psi_gt.to_numpy()[i, :])).dot(Q_gt.to_numpy().T)
pd.testing.assert_frame_equal(pd.DataFrame(C), pd.DataFrame(C_gt), rtol=1e-10, check_exact=False)
Loading