Skip to content

Feature: Updates for Space Ranger 4.0#9978

Draft
stephenwilliams22 wants to merge 4 commits into
satijalab:mainfrom
stephenwilliams22:stephen/spaceranger-4.0
Draft

Feature: Updates for Space Ranger 4.0#9978
stephenwilliams22 wants to merge 4 commits into
satijalab:mainfrom
stephenwilliams22:stephen/spaceranger-4.0

Conversation

@stephenwilliams22

@stephenwilliams22 stephenwilliams22 commented Jul 1, 2025

Copy link
Copy Markdown
Contributor

Updates include helpers and readers for Space Ranger cell segmentation.

Integrates 10x cell segmentations of visium HD data into the Seurat object.

Issues

  • Converting the SF object into a data.frame and back into an SF object in Read10X_Segmentations for CreateFOV seems like it should be unnecessary but is required
  • Should probably make the code for loading the segmentations in Load10X_Spatial a function?
  • Associating a tissue image with the segmentations
  • Need clarity between counts and data slots for the segmented cell matrix
  • ImageFeaturePlot and ImageFeaturePlot DO plot the cell polygons correctly but If we could use geom_sf in SpatialFeaturePlot I think that would be more desirable as this will automatically hold the tissue image as well

@stephenwilliams22
stephenwilliams22 marked this pull request as draft July 1, 2025 19:53
@stephenwilliams22

Copy link
Copy Markdown
Contributor Author

@jsicherman it would be great if you could have a look at this.

Comment thread R/preprocessing.R
Comment thread R/preprocessing.R Outdated
Comment thread R/preprocessing.R

st_coords <- merge(
as.data.frame(sf::st_coordinates(coordinates)),
data.frame(

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree with OP that it would be nice to have a CreateFOV.sfc or similar that allows this construction without having to do two round trips through polygon construction. Not sure if such a method already exists in Seurat

Comment thread R/preprocessing.R
)
{

image <- png::readPNG(source = file.path(image.dir, image.name))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is unused?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, we need to get the tissue image in there at some point so I left it in.

Comment thread R/preprocessing.R
segmentation.fov <- Read10X_Segmentations(image.dir = paste0(seg.data.dir, "spatial"), data.dir = data.dir, cell.names = segmentation.count.cellIDs)
segmentation.object[["slice1.polygons"]] <- segmentation.fov
object <- merge(x = object, y = segmentation.object)
DefaultAssay(object = object) <- segmentation.assay.name

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure if it's intuitive to have this create two assays and merge them together, rather than just one or the other. Will defer to you since you look at this data more, though.

Also, this output won't exist for Visium SD, which is also loaded through this preprocessing function, right? Should we raise a more informative error in those cases?

Comment thread R/preprocessing.R
if(load.segmentations) {
segmentation.assay.name <- "Segmentations"
seg.data.dir <- paste0(data.dir, "/segmented_outputs/")
seg.counts.path <- paste0(seg.data.dir, "filtered_feature_cell_matrix.h5")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: filename

@jsicherman

Copy link
Copy Markdown
Contributor

@stephenwilliams22 what do you mean when you say the polys aren't plotted correctly? Are they not closed, or merged together or something?

@stephenwilliams22

Copy link
Copy Markdown
Contributor Author

@stephenwilliams22 what do you mean when you say the polys aren't plotted correctly? Are they not closed, or merged together or something?

I'm not totally sure but if you look here they just look like balls of twine.

image

@jsicherman

Copy link
Copy Markdown
Contributor

@stephenwilliams22 looks like the vertices aren't ordered sequentially, which is weird if you could construct and plot them without issue in your original sfc? But also, how many vertices do you have per cell segmentation? Might be worth simplifying them if they're as complex as that screenshot seems to imply

@stephenwilliams22

Copy link
Copy Markdown
Contributor Author

@stephenwilliams22 looks like the vertices aren't ordered sequentially, which is weird if you could construct and plot them without issue in your original sfc? But also, how many vertices do you have per cell segmentation? Might be worth simplifying them if they're as complex as that screenshot seems to imply

fixed. ordering was the issue

@YoukaiFromAccounting

Copy link
Copy Markdown
Contributor

Hey @stephenwilliams22, I am trying to test the new Load10x_Spatial and Read10x_Segmentations functions with a sample V3D object (https://www.10xgenomics.com/datasets/visium-hd-three-prime-mouse-embryo-fresh-frozen). Currently I am running into the following issue:

If I do not specify an image in Load10X_Spatial ie:

v3d <- Load10X_Spatial(
  data.dir = data.dir,
  filename = "filtered_feature_cell_matrix.h5",
  slice = "slice1",
  image = NULL,
  load.segmentations = TRUE
)

Then I get the following error when trying to run Load10X_Spatial:

Error in if (tools::file_ext(filename) == "parquet") { : 
  argument is of length zero

It seems that without an image, the function tries to automatically call Read10X_Image() which attempts to locate a spatial/tissue_positions.parquet file, which does not exist for V3D objects. I was able to get Read10X_Segmentations working on this V3D object however:

image

@stephenwilliams22

Copy link
Copy Markdown
Contributor Author

v3d <- Load10X_Spatial(
data.dir = data.dir,
filename = "filtered_feature_cell_matrix.h5",
slice = "slice1",
image = NULL,
load.segmentations = TRUE
)

@YoukaiFromAccounting you do not need to use filename = "filtered_feature_cell_matrix.h5", that is implied when load.segmentations = TRUE. Do you think we should make that another parameter to the function? I don't think people go and change these file names very often (if ever). Also, does your data.dir, point to the top level of the pipeline outputs like this?

binned_outputs
segmented_outputs
spatial
Visium_HD_3prime_Mouse_Embryo_barcode_mappings.parquet
Visium_HD_3prime_Mouse_Embryo_binned_outputs.tar.gz
Visium_HD_3prime_Mouse_Embryo_cloupe_008um.cloupe
Visium_HD_3prime_Mouse_Embryo_cloupe_cell.cloupe
Visium_HD_3prime_Mouse_Embryo_feature_slice.h5
Visium_HD_3prime_Mouse_Embryo_metrics_summary.csv
Visium_HD_3prime_Mouse_Embryo_molecule_info.h5
Visium_HD_3prime_Mouse_Embryo_segmented_outputs.tar.gz
Visium_HD_3prime_Mouse_Embryo_spatial.tar.gz
Visium_HD_3prime_Mouse_Embryo_web_summary.html

The Load10X_Spatial function is intended to point to the top level. Maybe you pointed it to segmented_outputs?

@YoukaiFromAccounting

YoukaiFromAccounting commented Jul 8, 2025

Copy link
Copy Markdown
Contributor

@stephenwilliams22 Thanks for your help; I was able to get it working (I also switched to a smaller V3D dataset https://www.10xgenomics.com/datasets/visium-hd-three-prime-zebrafish-head-fresh-frozen). I am able to get a visualization if I run the following:

#Complete dataset path
data.dir <- "~/spaceranger_zebrafish"

#Load expression data and spatial image
v3d <- Load10X_Spatial(
  data.dir = data.dir,
  slice = "slice1",
  load.segmentations = TRUE
)

#Check existing boundary types
Boundaries(v3d[["slice1.polygons"]])
seg <- v3d[["slice1.polygons"]]@boundaries[["segmentation"]]
seg

#Inspect segmentations
DefaultBoundary(v3d[["slice1.polygons"]]) <- "segmentation"

ImageDimPlot(
  v3d,
  fov = "slice1.polygons",
  border.color = "white",
  border.size = 0.1
)

which gets me the following visualization:
image

Zoomed in visualization:
image

@stephenwilliams22

Copy link
Copy Markdown
Contributor Author

@stephenwilliams22 Thanks for your help; I was able to get it working (I also switched to a smaller V3D dataset https://www.10xgenomics.com/datasets/visium-hd-three-prime-zebrafish-head-fresh-frozen). I am able to get a visualization if I run the following:

Very cool! Do you think you all can take it from here to get the tissue image in the background? I think we also need to test if the regular data normalization workflow is working properly. Also, I'm wondering if this should be rewritten to use geom_sf which is much easer.

@YoukaiFromAccounting

Copy link
Copy Markdown
Contributor

@stephenwilliams22 I'm not quite sure what you mean by using geom_sf; do you mean extracting the segmentation polygons from an sf object and plotting those with ggplot instead of using ImageDimPlot?

@stephenwilliams22

Copy link
Copy Markdown
Contributor Author

@stephenwilliams22 I'm not quite sure what you mean by using geom_sf; do you mean extracting the segmentation polygons from an sf object and plotting those with ggplot instead of using ImageDimPlot?

Sorry, what i meant was in reference to my last checkbox at the top of the page. Right now we are implementing this in a Xenium fashion which does some back and forth making the polygons which are already in an sf object to a data.frame and then back to sf. This is necessary because xenium segmentations are not provided as a geojson. What would be nice is if we provided a path to the user to go through SpatialFeaturePlot where we could update that code to use geom_sf instead of drawing the polygons "by hand". I think that users would find this flow more intuitive since this is how the original visium assay works for visualization

@rsatija

rsatija commented Jul 8, 2025

Copy link
Copy Markdown
Collaborator

Hi Stephen - we've been looking over this. Do you have example code (doesn't have to use Seurat at all) for

  1. how to load an HD data,set this one for example, and plot the segmentations with geom_sf in a way that avoids the conversion you mentioned?
  2. ideally this example plots a tissue image as well

If you have this, we can certainly take the lead as using that as a prototype for updating the Seurat functions.

@dixinSJ

dixinSJ commented Jul 22, 2025

Copy link
Copy Markdown

How is this work progressing?

@YoukaiFromAccounting

Copy link
Copy Markdown
Contributor

We recommend that individuals interested in this update check out our Discussions board at (#9991) for questions/concerns users may have.

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

Successfully merging this pull request may close these issues.

5 participants