Join GitHub today
GitHub is home to over 40 million developers working together to host and review code, manage projects, and build software together.
Sign upFeatureHeatmap plot masking cells #235
Comments
This comment has been minimized.
This comment has been minimized.
|
Hi, You can decrease the size of your points, and use Regarding the plotted data, Best, |
This comment has been minimized.
This comment has been minimized.
|
Hi Leon, Thanks for your response. I used the recommended parameters but the contrast is still very poor. I was thinking of putting a min.cutoff to remove the lowly expressed cells. I couldn't find the cutoff format in the documentation. Can you please help me with that? I want to select cells with an expression of >2. Thanks, Biba |
This comment has been minimized.
This comment has been minimized.
|
Also, is there a way to plot a group of genes belonging to one pathway in a single feature plot or heatmap based on their average/median expression? |
This comment has been minimized.
This comment has been minimized.
|
Hi, I wrote a script that tries to do two things at once. It allows either to add a transparency to all your points, which you can define by setting a value below 1 to # Function to pseudo customize FeaturePlots
customize_Seurat_FeaturePlot <- function(p, alpha.use = 1, gradient.use = c("yellow", "red"), expression.threshold = NULL, is.log1p.transformed = F) {
#### Main function ####
main_function <- function(p = p, alpha.use = alpha.use, gradient.use = gradient.use, expression.threshold = expression.threshold, is.log1p.transformed = is.log1p.transformed) {
# Remove cells having an expression below a certain threshold
if (!is.null(expression.threshold)) {
if (isTRUE(is.log1p.transformed)) {
p$data <- p$data[p$data$gene >= expression.threshold,]
} else {
p$data <- p$data[p$data$gene >= log1p(expression.threshold),]
}
}
# Fill points using the gene expression levels
p$layers[[1]]$mapping$fill <- p$layers[[1]]$mapping$colour
# Define transparency of points
p$layers[[1]]$mapping$alpha <- alpha.use
# Change fill and colour gradient values
p <- p + scale_colour_gradientn(colours = gradient.use, guide = F) +
scale_fill_gradientn(colours = gradient.use, name = expression(atop(Expression, (log)))) +
scale_alpha_continuous(range = alpha.use, guide = F)
}
#### Execution of main function ####
# Apply main function on all features
p <- lapply(X = p, alpha.use = alpha.use, gradient.use = gradient.use,
expression.threshold = expression.threshold, is.log1p.transformed = is.log1p.transformed,
FUN = main_function)
# Arrange all plots using cowplot
# Adapted from Seurat
# https://github.com/satijalab/seurat/blob/master/R/plotting.R#L1100
# ncol argument from Josh O'Brien
# https://stackoverflow.com/questions/10706753/how-do-i-arrange-a-variable-list-of-plots-using-grid-arrange
cowplot::plot_grid(plotlist = p, ncol = ceiling(sqrt(length(p))))
}
# Plot features using FeaturePlot, and return individual plots using 'do.return = T'
# Store output in 'plot'
plot <- FeaturePlot(object = object, features.plot = c("Actb", "Rps9"), cols.use = c("yellow", "red"),
pt.size = 2, pch.use = 16, no.legend = F, do.return = T)
# Remove from plots all cells having an expression level below 2 (cutoff not log1p transformed)
customize_Seurat_FeaturePlot(p = plot, expression.threshold = 2)Hope that helps! Best, |
This comment has been minimized.
This comment has been minimized.
|
Regarding your second question, I am not aware of a Seurat function that can do that for you. I don't think that it is also common and good practice to compute median expression values of multiple genes for a given cell. In this case, you might want to use the scaled data from Seurat, and compute the median scaled expression levels of multiple genes. However, this is a completely different topic than what this issue was about. Best, |
This comment has been minimized.
This comment has been minimized.
|
Hi again, Sorry but I forgot that you were using # Function to pseudo customize FeatureHeatmap
customize_Seurat_FeatureHeatmap <- function(p, alpha.use = 1, gradient.use = c("yellow", "red"), expression.threshold = 0, is.log1p.transformed = F) {
# Remove cells having an expression below a certain threshold
if (isTRUE(is.log1p.transformed)) {
p$data <- p$data[p$data$expression >= expression.threshold,]
} else {
p$data <- p$data[p$data$expression >= log1p(expression.threshold),]
}
# Fill points using the gene expression levels
p$layers[[1]]$mapping$fill <- p$layers[[1]]$mapping$colour
# Define transparency of points
p$layers[[1]]$mapping$alpha <- alpha.use
# Change fill and colour gradient values
p <- p + scale_colour_gradientn(colours = gradient.use, guide = F) +
scale_fill_gradientn(colours = gradient.use, name = expression(atop(Scaled, expression))) +
scale_alpha_continuous(range = alpha.use, guide = F)
# Return plot
p
}
# Plot features using FeatureHeatmap, and return plot using 'do.return = T'
# Store output in 'plot'
plot <- FeatureHeatmap(object = crypts_hi_res, features.plot = c("Clu", "Lgr5", "Mex3a", "Yap1"), group.by = "class", sep.scale = F, pt.size = 1.5, cols.use = c("gray97", "blue"), pch.use = 1)
# Remove from plot all cells having an expression level below 2 (cutoff not log1p transformed)
# Filter is applied on log normalized data, but scaled data is plotted
customize_Seurat_FeatureHeatmap(plot, gradient.use = c("gray97", "blue"), expression.threshold = 2)Best, |
This comment has been minimized.
This comment has been minimized.
|
Thanks a lot Leon. You have been a great help. |
This comment has been minimized.
This comment has been minimized.
|
Hi Leon, Both the customized plots are working well. The only thing is that the background cells (ones without any expression of the specified genes) are disappearing from the plots. It is important for me to keep the tSNE plot whole to make the comparisons between the clusters. Can you please tell me what I can do to plot the background as well? Thanks, Biba |
This comment has been minimized.
This comment has been minimized.
|
Hello, Could you please share the code you are using? Providing also a plot before and after the operation you are doing using the script I wrote would be also helpful for me to troubleshoot your issue. Best, |
This comment has been minimized.
This comment has been minimized.
|
I understand. My bad! I wrote you a script that allows you to filter out the cells that have an expression level of the gene below the threshold that you specify using the #### For FeatureHeatmap() ####
# Plot features using FeatureHeatmap, and return plot using 'do.return = T'
# Store output in 'plot'
plot <- FeatureHeatmap(object = crypts_hi_res, features.plot = c("Clu", "Lgr5", "Mex3a", "Yap1"), group.by = "class", sep.scale = F, pt.size = 1.5, cols.use = c("gray97", "blue"), pch.use = 1)
# Order data by gene expresion level
plot$data <- plot$data[order(plot$data$expression),]
# plot with reordered data
plot
#### For FeaturePlot() ####
# Plot features using FeaturePlot, and return individual plots using 'do.return = T'
# Store output in 'plot'
plot <- FeaturePlot(object = object, features.plot = c("Actb", "Rps9"), cols.use = c("yellow", "red"),
pt.size = 2, pch.use = 16, no.legend = F, do.return = T)
# For each element of plot, reorder the data and return plot
plot <- lapply(X = plot, function(p) { p$data <- p$data[order(p$data$gene),]; p})
# Arrange all plots using cowplot
# Adapted from Seurat
# https://github.com/satijalab/seurat/blob/master/R/plotting.R#L1100
# ncol argument adapted from Josh O'Brien
# https://stackoverflow.com/questions/10706753/how-do-i-arrange-a-variable-list-of-plots-using-grid-arrange
cowplot::plot_grid(plotlist = plot, ncol = ceiling(sqrt(length(plot))))Hope that helps! Best, |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
|
Hello, Here you go. #### For FeaturePlot() ####
# Function to pseudo customize FeaturePlots
customize_Seurat_FeaturePlot <- function(p, alpha.use = 1, gradient.use = c("yellow", "red"), expression.threshold = 0, is.log1p.transformed = F) {
#### Main function ####
main_function <- function(p = p, alpha.use = alpha.use, gradient.use = gradient.use, expression.threshold = expression.threshold, is.log1p.transformed = is.log1p.transformed) {
# Order data by gene expresion level
p$data <- p$data[order(p$data$gene),]
# Define lower limit of gene expression level
if (isTRUE(is.log1p.transformed)) {
expression.threshold <- expression.threshold
} else {
expression.threshold <- log1p(expression.threshold)
}
# Compute maximum value in gene expression
max.exp <- max(p$data$gene)
# Fill points using the gene expression levels
p$layers[[1]]$mapping$fill <- p$layers[[1]]$mapping$colour
# Define transparency of points
p$layers[[1]]$mapping$alpha <- alpha.use
# Change fill and colour gradient values
p <- p + scale_colour_gradientn(colours = gradient.use, guide = F, limits = c(expression.threshold, max.exp), na.value = "grey") +
scale_fill_gradientn(colours = gradient.use, name = expression(atop(Expression, (log))), limits = c(expression.threshold, max.exp), na.value = "grey") +
scale_alpha_continuous(range = alpha.use, guide = F)
}
#### Execution of main function ####
# Apply main function on all features
p <- lapply(X = p, alpha.use = alpha.use, gradient.use = gradient.use,
expression.threshold = expression.threshold, is.log1p.transformed = is.log1p.transformed,
FUN = main_function)
# Arrange all plots using cowplot
# Adapted from Seurat
# https://github.com/satijalab/seurat/blob/master/R/plotting.R#L1100
# ncol argument adapted from Josh O'Brien
# https://stackoverflow.com/questions/10706753/how-do-i-arrange-a-variable-list-of-plots-using-grid-arrange
cowplot::plot_grid(plotlist = p, ncol = ceiling(sqrt(length(p))))
}
#### For FeatureHeatmap() ####
# Function to pseudo customize FeatureHeatmap
customize_Seurat_FeatureHeatmap <- function(p, alpha.use = 1, gradient.use = c("yellow", "red"), scaled.expression.threshold = NULL, is.log1p.transformed = F) {
# Order data by gene expresion level
p$data <- p$data[order(p$data$scaled.expression),]
# Define lower limit of scaled gene expression level
if (!is.null(scaled.expression.threshold)) {
if (isTRUE(is.log1p.transformed)) {
scaled.expression.threshold <- scaled.expression.threshold
} else {
scaled.expression.threshold <- log1p(scaled.expression.threshold)
}
} else if (is.null(scaled.expression.threshold)) {
scaled.expression.threshold <- min(p$data$scaled.expression)
}
# Compute maximum value in gene expression
max.scaled.exp <- max(p$data$scaled.expression)
# Fill points using the gene expression levels
p$layers[[1]]$mapping$fill <- p$layers[[1]]$mapping$colour
# Define transparency of points
p$layers[[1]]$mapping$alpha <- alpha.use
# Change fill and colour gradient values
p <- p + scale_colour_gradientn(colours = gradient.use, guide = F, limits = c(scaled.expression.threshold, max.scaled.exp), na.value = "grey") +
scale_fill_gradientn(colours = gradient.use, name = expression(atop(Scaled, expression)), limits = c(scaled.expression.threshold, max.scaled.exp), na.value = "grey") +
scale_alpha_continuous(range = alpha.use, guide = F)
# Return plot
p
}Note that for Hope that helps! Best, |
This comment has been minimized.
This comment has been minimized.
|
My bad! For #### For FeatureHeatmap() ####
# Function to pseudo customize FeatureHeatmap
customize_Seurat_FeatureHeatmap <- function(p, alpha.use = 1, gradient.use = c("yellow", "red"), scaled.expression.threshold = NULL) {
# Order data by scaled gene expresion level
p$data <- p$data[order(p$data$scaled.expression),]
# Define lower limit of scaled gene expression level
if (!is.null(scaled.expression.threshold)) {
scaled.expression.threshold <- scaled.expression.threshold
} else if (is.null(scaled.expression.threshold)) {
scaled.expression.threshold <- min(p$data$scaled.expression)
}
# Compute maximum value in gene expression
max.scaled.exp <- max(p$data$scaled.expression)
# Fill points using the scaled gene expression levels
p$layers[[1]]$mapping$fill <- p$layers[[1]]$mapping$colour
# Define transparency of points
p$layers[[1]]$mapping$alpha <- alpha.use
# Change fill and colour gradient values
p <- p + scale_colour_gradientn(colours = gradient.use, guide = F, limits = c(scaled.expression.threshold, max.scaled.exp), na.value = "grey") +
scale_fill_gradientn(colours = gradient.use, name = expression(atop(Scaled, expression)), limits = c(scaled.expression.threshold, max.scaled.exp), na.value = "grey") +
scale_alpha_continuous(range = alpha.use, guide = F)
# Return plot
p
} |
This comment has been minimized.
This comment has been minimized.
|
Thanks a lot Leon. They work like dream. |
This comment has been minimized.
This comment has been minimized.
|
Hi @ghoshal, I had a similar situation where I needed to bring the points that correspond to high expression to the front in a feature plot. I tried the solutions above in this and the other thread (issue #757), but ultimately, what worked best for me is to directly re-order the "$data" data frame in increasing order of gene expressions. Here is an example code snippet: # First, the usual command to make the feature plots and return the ggplot2 objects
fp <- Seurat::FeaturePlot(object=p, features.plot=GeneList, cols.use = c("gray75", "red"),
min.cutoff="q25",max.cutoff="q75", reduction.use = "tsne",
do.return=TRUE)
# Here, fp is a list of objects, one per feature plot
# Then, re-order the "data" dataframe in increasing order of gene expressions
for (i in 1:length(fp)){
fp[[i]]$data <- fp[[i]]$data[order(fp[[i]]$data$gene),]
}This did the trick for me! That is, I got all the gray points relegated to the back. Among the non-gray ones, the brightest red points were at the very front, and other shades of red at intermediate positions. If a dull red point and a bright red point overlap, then the bright red one would be at the front, which is exactly what I wanted. Hope this helps. Sample plots attached below. |
This comment has been minimized.
This comment has been minimized.
|
Hi @CodeInTheSkies, The principle is exactly the same in both cases. Best, |
This comment has been minimized.
This comment has been minimized.
|
Hi @leonfodoulian, Thanks! |
This comment has been minimized.
This comment has been minimized.
with Seurat V3, this is not working. where the data slot in the ggplot object now? there is no p$data$genep$data$ Thank you! |
This comment has been minimized.
This comment has been minimized.
In Seurat v3, FeaturePlot now has baked in tools for ordering and filtering (so you don't need these functions for these plotting features): The only thing it doesn't implement now is ALPHA. Which would be awesome. |





Hi,
I am using FeatureHeatmap to visualize gene expression between two groups. When I plot, the cells with no expression are masking the cells that have an expression as you can see on the left side. Is there a way to not let this happen.
FeatureHeatmap(object = crypts_hi_res, features.plot = c("Clu", "Lgr5", "Mex3a", "Yap1"), group.by = "class", sep.scale = F, pt.size = 1.5, cols.use = c("gray97", "blue"), pch.use = 1)
Also, when we are plotting gene expression in either FeaturePlot or FeatureHeatmap, are we plotting the scaled log normalized data?
Thanks,
Bibaswan