bnprks / BPCells

Scaling Single Cell Analysis to Millions of Cells
https://bnprks.github.io/BPCells
Other
134 stars 11 forks source link

RSpectra::eigs()/eigs_sym() compatibility with BPCells #54

Open PietroAndrei opened 8 months ago

PietroAndrei commented 8 months ago

Hello,

I am trying to use BPCells to work with a large connectivity matrix, and ideally I would need to apply the eigs_sym() function from RSpectra to extract the top k eigenvalues/vectors from that matrix. Is there a way to make the BPCells matrix compatible with this additional RSpectra function?

Thank you for your help :)

Pietro

bnprks commented 8 months ago

Hi Pietro, First a clarification note for others where an SVD is sufficient -- BPCells has an svds function which internally uses the same C++ Spectra solver that the RSpectra package uses for SVDs. If your matrix $A$ can be expressed as $A = XX^T$, then an SVD of $X$ is sufficient to find the top eigenvalues/vectors of $A$.

If you want eigenvalues/vectors in a general case, I would recommend you use the "function" interface of RSpectra. Drawing from the examples in their README it might look something like:

f <- function(x, args) args %*% x
g <- function(x, args) x %*% args
RSpectra::eigs_sym(f, k, Atrans = g, dim = dim(bpcells_mat), args = bpcells_mat)

For more details I'd refer you to the RSpectra documentation, but in general solvers like RSpectra and irlba which allow input of a custom matrix-vector multiply function can be readily adapted to work with BPCells matrices.

-Ben

PietroAndrei commented 8 months ago

Hi Ben,

thanks a lot for the explanation! I was aware of the function format in RSpectra, but I never tried to use it.

Just to clarify: I am working with a symmetric matrix representing spatial interactions, and I am not sure if/how the resulting left and right eigenvectors from svds() would be applicable for the downstream analysis that I am planning to do

bnprks commented 7 months ago

Hi Pietro, did you have a remaining BPCells question on this issue? I can't speak the particular analysis you're running, but if you have remaining BPCells-related questions after trying the RSpectra function interface I'd be happy to answer

PietroAndrei commented 7 months ago

Hi Ben,

following your advice, I think I've managed to combine BPCells and RSpectra correctly, so I don't think I have other questions. However, I just wanted to point out that you might want to make BPCells compatible with the 'CsparseMatrix' format, which apparently should substitute 'dgCMatrix'.

library(BPCells)
library(dplyr)
library(Matrix)

tmpdir_M = tempfile('mat')
M = Diagonal(1000)

M = as(M,'CsparseMatrix') %>% write_matrix_dir(.,dir=tmpdir_M,overwrite=T)

#Error: In function write_matrix_dir: "mat" must have class IterableMatrix, or dgCMatrix
#    ▆
 #1. ├─as(M, "CsparseMatrix") %>% ...
 #2. └─BPCells::write_matrix_dir(., dir = tmpdir_M, overwrite = T)
 #3.   └─BPCells:::assert_is(mat, c("IterableMatrix", "dgCMatrix"))

M = as(M,'dgCMatrix') %>% write_matrix_dir(.,dir=tmpdir_M)

#Warning message:
#'as(<ddiMatrix>, "dgCMatrix")' is deprecated.
#Use 'as(as(., "generalMatrix"), "CsparseMatrix")' instead.
#See help("Deprecated") and help("Matrix-deprecated").