saeyslab / nichenetr

NicheNet: predict active ligand-target links between interacting cells
452 stars 113 forks source link

cannot complete assign_ligands_to_celltype #268

Closed shawnshu1 closed 1 month ago

shawnshu1 commented 1 month ago

finished nichenet_output, and trying to run assign_ligands_to_celltype for circos plot. error message, Error in data.frame(ligand_type = sender, ligand = unique_ligands_sender) : arguments imply differing number of rows: 1, 0

shawnshu1 commented 1 month ago

fixed the issue after debugging through the source code (application_visualization.R). Also detected additional bugs! Line 826, apply(GetAssayData(seuratObj_subset[, seuratObj_subset[[celltype_col]] == celltype], slot = slot), 1, func.agg) for Seurat5, use: apply(GetAssayData(seuratObj_subset[, seuratObj_subset[[celltype_col]] == celltype], layer = "counts"), 1, func.agg)

Line 831, set_rownames(ligands). This line needs to be deleted. the data frame resulting from Line 830 already has ligand as rownames, whose order is actually DIFFERENT from the vector ligands

Line 844, data.frame(ligand_type = sender, ligand = unique_ligands_sender) When unique_ligands_sender returns an empty character, this will create the error: Error in data.frame(ligand_type = sender, ligand = unique_ligands_sender) : arguments imply differing number of rows: 1, 0

A conditional flow in the following will mitigate such error if (length(unique_ligands_sender) > 0) { return(data.frame(ligand_type = sender, ligand = unique_ligands_sender)) }

csangara commented 1 month ago

Hi @shawnshu1, Thank you for noticing the bugs and providing a solution. Apologies for taking some time to get around to this. In the pull request, I have incorporated your condition statement and removed the set_rownames line. Additionally, I added the ... argument to allow users to provide either the 'slot' or 'layer' argument depending on their Seurat version.

I looked into the names mismatch, and it seems to be due to the different behavior of subset with v5 objects. Prior to v5, the row names of the subsetted Seurat object will follow the order of the provided vector. In v5, the Seurat object retains its original order. Example:

# Load test object
seurat_obj_test <- readRDS(url("https://zenodo.org/record/3531889/files/seuratObj_test.rds"))

# Update object, but underlying structure is still that of v3
seurat_obj_test <- UpdateSeuratObject(seurat_obj_test)

# Randomly get 20 genes from the object
random_ligands <- sample(rownames(seurat_obj_test), 20)

# This returns TRUE
all(rownames(subset(seurat_obj_test, features = random_ligands)) == random_ligands)

# Create new v5 object
seurat_obj_test_v5 <- CreateSeuratObject(counts = seurat_obj_test@assays$RNA@counts)

# This returns FALSE
all(rownames(subset(seurat_obj_test_v5, features = random_ligands)) == random_ligands)

I was not aware of this until now, and I will proceed to check other subset calls we make in our package. We really appreciate your help!

This issue will automatically be closed once I merge the PR, but feel free to reopen this should you still encounter bugs.