BayesSpace icon indicating copy to clipboard operation
BayesSpace copied to clipboard

spatialEnhance across multiple samples randomly allocates colours

Open PIR015 opened this issue 2 years ago • 16 comments

Hi,

I ran BayesSpace across multiple samples using an integrated Seurat object as a starting point. I have created a palette for this integrated analysis, which I use for my DimPlots and SpatialDimPlots. When I plot the BayesSpace plots I get different order in the clusters colours for each sample, I have tried to use the init=T argument in spatialEnhance for the initial cluster assignments for spots, but it has failed.

My question is if there is any way to have the clusters organised the same way in each spatialEnhance plot, matching the DimPlot and SpatialDimPlot cluster colours.

Thank you in advance!

Patricia

PIR015 avatar Jan 19 '22 13:01 PIR015

Hi Patricia,

You can specify your color palette using the palette argument of clusterPlot().

The init parameter in spatialEnhance() allows you to set initial cluster assignments (at the spot level), so this should be a vector with length equal to the number of spots.

If you want to reorder the clustering numbers, you can try this:

#first run spatialEnhance
sce.enhanced$spatial.cluster.reordered = factor(sce.enhanced$spatial.cluster, 
                                                levels = c(3,1,2,5,4)) #replace levels with the order of clusters you want
myPalette = c("#000000", "#E69F00", "#56B4E9", "#009E73", "#F0E442")
clusterPlot(sce.enhanced, label = "spatial.cluster.reordered", palette = myPalette)

edward130603 avatar Jan 20 '22 19:01 edward130603

Hi, thank you for this. It continues to give me different colours as my UMAP and SpatialDimPlots, and when I try to rearrange it doesn't always assign the same number to the colour, so when I change one, all the rest are also changed somehow randomly.

PIR015 avatar Jan 24 '22 10:01 PIR015

hm, I'm not super sure what's going on here. Did you harmonize/integrate the PCs before running BayesSpace? Our joint clustering vignette goes through how to run BayesSpace across multiple samples in order to get clusters that are aligned between different samples.

If you can provide some of your plotting code (as well as whatever outputs you are able to share), that might be helpful for me to debug as well.

edward130603 avatar Jan 25 '22 17:01 edward130603

Hi,

Thank you, I have harmonised and integrated before running BayesSpace.

Here is my plotting code:

#Script 3

palette <- c("#0C5BB0FF", "#EE0011FF", "#15983DFF", "#EC579AFF", "#FA6B09FF", "#149BEDFF", "#A1C720FF", "#FEC10BFF", "#16A08CFF", "#9A703EFF")

sce1.1e$spatial.cluster.reordered = factor(sce1.1e$spatial.cluster, levels = c(1,2,3,4,5,6,7))

S1B <- clusterPlot(sce1.1e, size=0.1, label = "spatial.cluster.reordered", palette=palette) + labs(title="Enhanced clustering")

saveRDS(S1B, file= "S1B.rds")

Thank you once again!

PIR015 avatar Jan 25 '22 17:01 PIR015

Ok, I'm still not sure if I understand the problem. Are the clusters matching between your UMAP/SpatialDimPlots and your BayesSpace plots (and just the colors don't correspond)? Or is it completely scrambled? Where are your cluster labels for the Seurat plots coming from (@indent in the Seurat object)?

When you run spatialEnhance(), are you setting init equal to the Seurat clusters for that sample? This should ensure that your enhanced clusters will map back to the same ones you have in Seurat.

edward130603 avatar Jan 26 '22 17:01 edward130603

Hi Edward, sorry for the late reply.

I have revisited this now and the clusters are not matching SpatialDimPlots to BayesSpace, which I called randomly allocated colours. I'm not sure I understand the second question where you mention the cluster labels coming from @ident in the Seurat object.

My code is this: sce1.15 = spatialPreprocess(sce1.15, platform = "Visium", skip.PCA = T, log.normalize = F) #add BayesSpace metadata, without messing with PCA/logcounts sce1.15 = spatialCluster(sce1.15, nrep = 50000, burn.in = 100, q = 7) #quickly cluster via BayesSpace q = number of clusters

sce1.15e <- spatialEnhance(sce1.15, q=7, platform="Visium", nrep=50000, gamma=2, verbose=TRUE, save.chain=TRUE, jitter_scale=3.5, jitter_prior=0.3)

The only time it says to assign anything related to clusters is "q=7" which is the number of clusters I have on my Seurat object.

I have tried setting init equal to Seurat clusters but it failed.

Thank you in advance!

PIR015 avatar Mar 08 '22 09:03 PIR015

I think the problem is right now, you are using the default initialization, and there is no guarantee these clusters will match up with those that you had in the Seurat object. You can set an initialization manually via the init parameter:

sce1.15 = spatialCluster(sce1.15, init = mySeuratObject@Ident, ...)
# or to enhance
sce1.15e = spatialEnhance(sce1.15, init = mySeuratObject@Ident, ...)

Did you try this and it failed? Was there an error message or did the results still just look scrambled?

Also would be good to check that the order of the spots (columns in the SCE) are the same between your SCE and Seurat objects. If not, rearrange your columns in SCE:

sce1.15 = sce1.15[, Cells(mySeuratObject)]

edward130603 avatar Mar 15 '22 05:03 edward130603

I have tried what you suggested and here are the outputs:

sce1e <- spatialEnhance(sce1, q=7, platform="Visium",

  •                     nrep=50000, gamma=2, 
    
  •                     verbose=TRUE, save.chain=TRUE,
    
  •                     jitter_scale=3.5, jitter_prior=0.3 , init = merging@Ident)
    

Error in spatialEnhance(sce1, q = 7, platform = "Visium", nrep = 50000, : no slot of name "Ident" for this object of class "Seurat"

sce1e <- spatialEnhance(sce1, q=7, platform="Visium",

Calculating neighbors... Fitting model... Error in iterate_deconv(Y = Y2, df_j = df_j, tdist = tdist, nrep = nrep, : copy into submatrix: incompatible matrix dimensions: 1x8382 and 1x205020

PIR015 avatar Mar 15 '22 13:03 PIR015

Ok, so your sce right now has 1397 spots. It seems like [email protected] has length of 34170. Maybe need to subset [email protected] to only sample 1.15.

edward130603 avatar Mar 15 '22 17:03 edward130603

Hi Edward,

I have tried what you suggested and got this back:

Neighbors were identified for 1392 out of 1397 spots. Fitting model... Calculating labels using iterations 100 through 50000. Calculating neighbors... Fitting model... 0% 10 20 30 40 50 60 70 80 90 100% [----|----|----|----|----|----|----|----|----|----| **************************************************| Calculating labels using iterations 10000 through 50000. You created a large dataset with compression and chunking. The chunk size is equal to the dataset dimensions. If you want to read subsets of the dataset, you should testsmaller chunk sizes to improve read times. You created a large dataset with compression and chunking. The chunk size is equal to the dataset dimensions. If you want to read subsets of the dataset, you should testsmaller chunk sizes to improve read times. You created a large dataset with compression and chunking. The chunk size is equal to the dataset dimensions. If you want to read subsets of the dataset, you should testsmaller chunk sizes to improve read times. Error in [.data.frame(cdata, , c(x, y, "subspot.idx", fill)) : undefined columns selected Calls: clusterPlot ... .make_triangle_subspots -> .select_subspot_positions -> [ -> [.data.frame Execution halted

It seems like it worked but execution was halted when plotting?

This is my code:

`#extract Slide1SampleA <- merging[,grepl("Slide1SampleA", merging$orig.ident, ignore.case=TRUE)]

sce1 = spatialPreprocess(sce1, platform = "Visium", skip.PCA = T, log.normalize = F) #add BayesSpace metadata, without messing with PCA/logcounts sce1 = spatialCluster(sce1, nrep = 50000, burn.in = 100, q = 7) #quickly cluster via BayesSpace q = number of clusters sce1e <- spatialEnhance(sce1, q=7, platform="Visium", nrep=50000, gamma=2, verbose=TRUE, save.chain=TRUE, jitter_scale=3.5, jitter_prior=0.3 , init = [email protected])

save.image("S1A.RData")

palette <- c("T Cell Rich Niche"="#0C5BB0FF", "Erythrocytes"="#EE0011FF", "B Cell Rich Niche"="#15983DFF", "COMP+ Fibroblast Niche"="#EC579AFF", "APOD+ GAS5+ FABP4+"="#FA6B09FF", "Vascular Niche"="#149BEDFF", "Lining Layer Cells"= "#A1C720FF")

S1A <- clusterPlot(sce1e, size=0.1, label = "clusters", palette=palette) + labs(title="Enhanced clustering")

saveRDS(S1A, file= "S1A.rds")

`

It also didn't save image.

Thanks

PIR015 avatar Mar 21 '22 13:03 PIR015

Yes, this is the relevant error message:

Error in [.data.frame(cdata, , c(x, y, "subspot.idx", fill)) :
undefined columns selected

Can you check the column names of sce1e? I'm guessing for plotting, you should use label = "spatial.cluster" which is the default column for storing the spatial clusters.

Best, Edward

edward130603 avatar Mar 22 '22 23:03 edward130603

The problem I have is spatial.cluster column is numbers (of the clusters), when I try to plot it with the palette it doesn't assign any colour because it is looking for the names, and even if I assign a new column with the named clusters, so instead of numbers I'd have the actually names in my palette, it doesn't assign it to the right spots. My guess is that Bayesspace is giving each cluster its number randomly and not based on the original seurat clusters so if I name cluster 1 as T cells in my seurat object, it might not be the same in the bayesspace enhanced object.

PIR015 avatar Mar 25 '22 10:03 PIR015

I have the same problem. My clusters loose their naming and are ordered randomly.

Looking at line 76 in the source code for spatialEnhance() there is:

enhanced$spatial.cluster <- unname(labels)

I aussme the function is written to reomve revious labels?

I have tried to delete this line and redifine the function, but it did not work.

Can you help us out? Thanks Chris

chrismahony avatar Mar 25 '22 12:03 chrismahony

Can you both try plotting just your initialization using BayesSpace's clusterPlot() function? Does this match your Seurat plot? If not:

  • If the clusters are completely scrambled, check the order of spots in your SCE (colnames(mySce)) and reorder to match Seurat obj. #58 has an example of this type of issue.
  • If the clusters look right but colors are off, relevel your initialization or the palette

BayesSpace clusters will be based off of the initialization, so if your initialization has cluster 1 as T cells, it will likely remain T cells in the final result unless the initialization was very far off from the "optimal" spatial clustering partition.

edward130603 avatar Mar 28 '22 05:03 edward130603

Thanks for this.

My SCE object has all the metadata from Seurat I can run clusterplot() no problem and see my cluster IDs. After I run spatialEnhance() I loose all the meta data and the only cluster ID I have is the "spatial.cluster" slot. This is named in numbers and when I run clusterplot() there is no obvious correlation between e.g. T cells before spatialEnhance() and after in the "spatial.cluster". I have several samples and each time the assignment of T cells is random(or based on another parameter).

Ideally, the labels in "spatial.cluster" would retain their original names, is this possible?

Thanks Chris

chrismahony avatar Mar 28 '22 10:03 chrismahony

Unfortunately, we can't directly output character based cluster names at the moment, but if you know that "cluster 1" in your initialization maps to T cells, it should be straightforward to make a new column in your colData that maps the numbers to your named clusters and then plot that column instead of the default numeric spatial.cluster.

If you are using default initialization, then there is no way to map your final clusters to your annotations besides doing it manually by looking at which ones seem to match up. I recommend using the custom initialization inputted via the init parameter. Your previous annotations can be converted to numeric format using this:

custom.init = as.factor(my.annotations) #my.annotations will be a character vector with things like "T cells", "B cells", etc.
annotation.names = levels(custom.init) #save names 
mySCE$custom.init = as.numeric(custom.init) #put into SCE as numeric
mySCE$custom.init.named = annotation.names[mySCE$custom.init] #put named init into SCE as well
clusterPlot(mySCE, "custom.init.named") #check that spot-level initialization looks as expected
#if the above plot doesn't look right, you have some other issue
mySCE.enhanced = spatialEnhance(nrep = 1000, burn.in = 100, init = mySCE$custom.init, ...) #replace ... with your other parameters as necessary
mySCE.enhanced$named.spatial.clusters = annotation.names[mySCE.enhanced$spatial.cluster] #make new col with named clusters
clusterPlot(mySCE.enhanced, "named.spatial.clusters")

Does this approach work?

edward130603 avatar Mar 28 '22 19:03 edward130603