Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to distinguish between sender spots and receiver spots? stlearn distance =200 #315

Open
smk5g5 opened this issue Nov 18, 2024 · 0 comments

Comments

@smk5g5
Copy link

smk5g5 commented Nov 18, 2024

Hi,

I have some doubts about distinguishing sender spots from receiver spots?
I was also wondering how does one decide on a good distance (experimentally sensible) for visium data. I have used a distance of 200 (based on the distance argument in stlearn cci ). I was wondering if this is appropriate?

Also I have doubts about deciding which spots are receiver spots or sender spots.

I used the following code (in which I have 3 versions for deciding sender spots and receiver spots).

In the following code I have 3 versions (version 1 and 3 are similar) ,in those 2 versions I take the spot which is significant for a particular Ligand receptor pair and filter the neighbourhood spots (if it expresses receptor to some degree e.g. >1 or >2 etc) and further filter the Ligand based on expression of Ligand in the significant spot (i.e. if the ligand expression is not > 1 count I don't consider it). Although I have seen significant spots which don't show expression of that particular Ligand or receptor (and I was wondering why is that so)?

In the second version I just use the significant spots (assuming that the significant spots are the only ones which have spatially significant ligand and receptor expression (further filtering based on ligand and receptor expression in that spot being > 1 count).

So I was wondering what do you guys think about it? If this is the correct approach? If not what else would you recommend?

Thank you!

sigspots_senders_to_receiverspot_list <- function(sigspots_file, neighbourhood_spots_file, seurat_obj) {
  # Load the neighbourhood spots data
  neighbourhood_spots_df <- read.table(neighbourhood_spots_file, sep = " ", header = TRUE)

  # Create list to store sender spots and their neighborhoods
  sender_spot_neighborhood_list <- list()
  for (i in 1:nrow(neighbourhood_spots_df)) {
    sender_spot <- neighbourhood_spots_df$X[i]
    sender_spot_neighborhood_list[[sender_spot]] <- str_split(neighbourhood_spots_df$neighbour_bcs[i], ',')[[1]]
  }

  # Load significant spots data
  sigspots_df <- read.csv(sigspots_file, sep = ",", header = TRUE)
  sigspots_df_list <- split(sigspots_df, sigspots_df$LR_interaction)

  # Initialize list to store results
  LR_sender_receiver_spot_list <- list()

  # Iterate over each ligand-receptor interaction
  for (LR in names(sigspots_df_list)) {
    myligand <- str_split(LR, '_')[[1]][1]
    myrec <- str_split(LR, '_')[[1]][2]

    # Identify barcodes with expression for ligand and receptor
	# For version 1        receptor_barcodes <- names(which(seurat_obj@assays$Spatial@counts[myrec, ] > 0)) #to further filter neighborhood barcodes to only include higher expression barcodes for receptors

    #version 3 recepter expression > 2 and ligand expression > 2

    receptor_barcodes <- names(which(seurat_obj@assays$Spatial@counts[myrec, ] > 2)) #to further filter neighborhood barcodes to only include higher expression barcodes for receptors
    ligand_barcodes <- names(which(seurat_obj@assays$Spatial@counts[myligand, ] > 2))

    # Filter significant sender spots based on ligand expression
    mysig_sender_spots <- intersect(sigspots_df_list[[LR]]$Significant_barcodes, ligand_barcodes)

	# Version 3 is only use spots for a particular LR if they are in Significant_barcodes consider those which are 
    # Find receiver barcodes in the neighborhood of sender spots where receptor is expressed
    #version 3 recepter expression > 2 and ligand expression > 2


	# Version 2 is only use spots for a particular LR if they are in Significant_barcodes consider those which are 
    # Find receiver barcodes in the neighborhood of sender spots where receptor is expressed

    #Version 1 and version 3
    receptor_barcodes_in_neighbourhood <- lapply(sender_spot_neighborhood_list[mysig_sender_spots], function(x) {
      intersect(receptor_barcodes, x)
    })
    # Remove empty elements

    # Version 2 use receptors spots only if they are in mysig_sender_spots
    # receptor_barcodes_in_neighbourhood <- lapply(sender_spot_neighborhood_list[mysig_sender_spots], function(x) {
    #   abc = intersect(receptor_barcodes, x)
    #   return(intersect(abc,mysig_sender_spots))
    # })

    receptor_barcodes_in_neighbourhood <- Filter(function(x) length(x) > 0, receptor_barcodes_in_neighbourhood)

    # Skip if no valid sender spots or all neighborhoods are empty
    if (length(mysig_sender_spots) == 0 || length(receptor_barcodes_in_neighbourhood) == 0) {
      next
    }

    # Create data frames for each sender-receiver pair
    Sender_spot_receiver_spot_df_list <- lapply(names(receptor_barcodes_in_neighbourhood), function(x) { 
      mydf <- data.frame(receiver_spot = receptor_barcodes_in_neighbourhood[[x]])
      mydf$sender_spot <- x
      mydf$LR <- LR
      return(mydf[c('sender_spot', 'receiver_spot', 'LR')])
    })

    # Combine data frames into one for each LR interaction
    Sender_spot_receiver_spot_df <- do.call(rbind, Sender_spot_receiver_spot_df_list)
    LR_sender_receiver_spot_list[[LR]] <- Sender_spot_receiver_spot_df
  }

  # Combine all LR interaction data frames into a single data frame
  LR_sender_receiver_spot_df <- do.call(rbind, LR_sender_receiver_spot_list)

  # Add sample metadata to LR_sender_receiver_spot_df
  mysample_seurat_meta <- [email protected][c('integrated_snn_res.0.9')]
  mysample_seurat_meta$barcode <- rownames(mysample_seurat_meta)

  mysample_seurat_meta$integrated_snn_res.0.9 = droplevels(mysample_seurat_meta$integrated_snn_res.0.9)

  LR_sender_receiver_spot_df$Sample <- unique(seurat_obj$Sample)
  LR_sender_receiver_spot_df$Patient <- unique(seurat_obj$Patient)

  # Join metadata and rename columns correctly
  LR_sender_receiver_spot_df2 <- LR_sender_receiver_spot_df %>%
    left_join(mysample_seurat_meta, by = c("sender_spot" = "barcode")) %>%
    rename(sender_cluster = integrated_snn_res.0.9)
  
  LR_sender_receiver_spot_df3 <- LR_sender_receiver_spot_df2 %>%
    left_join(mysample_seurat_meta, by = c("receiver_spot" = "barcode")) %>%
    rename(receiver_cluster = integrated_snn_res.0.9)

  # Return the final data frame
  return(LR_sender_receiver_spot_df3)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant