Loading [MathJax]/jax/input/TeX/config.js
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >单细胞空间|在Seurat中对基于图像的空间数据进行分析(1)

单细胞空间|在Seurat中对基于图像的空间数据进行分析(1)

作者头像
数据科学工厂
发布于 2024-06-21 08:41:57
发布于 2024-06-21 08:41:57
77800
代码可运行
举报
运行总次数:0
代码可运行

引言

在这篇指南[1]中,我们介绍了Seurat的一个新扩展功能,用以分析新型的空间解析数据,将重点介绍由不同成像技术生成的三个公开数据集。

  • Vizgen MERSCOPE(用于小鼠大脑研究)
  • Nanostring CosMx空间分子成像仪(用于FFPE人类肺组织)
  • Akoya CODEX(用于人类淋巴结研究)

首先,我们将加载完成本指南所需的相关软件包。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
library(Seurat)
library(future)
plan("multisession", workers = 10)
library(ggplot2)

小鼠大脑:Vizgen MERSCOPE

这个数据集是通过Vizgen MERSCOPE系统生成的,该系统采用了MERFISH技术。整个数据集包含了九个样本(小鼠大脑的三个完整横截面,每个横截面有三个生物学重复样本)。基因面板涵盖了483个基因目标,包括了已知的典型细胞类型标志物、非感觉型G蛋白偶联受体(GPCRs)和受体酪氨酸激酶(RTKs)。

在本指南中,我们分析了其中一个样本——第二切片的第一个生物学重复样本。在每个细胞中检测到的转录本数量平均为206。

首先,我们导入数据集并构建了一个Seurat对象。

我们使用了我们自己编写的LoadVizgen()函数来读取Vizgen分析流程的结果。生成的Seurat对象包含了以下信息:一个计数矩阵,记录了每个细胞中483个转录本的观察分子数。这个矩阵在功能上与单细胞RNA测序中的计数矩阵相似,并且默认情况下存储在Seurat对象的RNA分析模块中。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
vizgen.obj <- LoadVizgen(data.dir = "/brahms/hartmana/vignette_data/vizgen/s2r1/", fov = "s2r1")

接下来的信息特定于成像分析,并存储在生成的 Seurat 对象的图像槽中:

  • 细胞中心定位:记录了每个细胞中心的位置信息。
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
head(GetTissueCoordinates(vizgen.obj[["s2r1"]][["centroids"]]))

##          x        y                                    cell
## 1 638.5640 4594.216 149164679103246548309819743981609972453
## 2 593.8034 4516.240 215843146921706462965382248182021894607
## 3 597.3134 4566.676 230248905804673613678286091156141465134
## 4 613.2434 4609.498 237155298815097057940587033798543926454
## 5 609.1934 4603.180 256099454901769634241742157204636917386
## 6 623.8814 4642.708  52442222147121971758529793775250916001
  • 细胞边界划分:用于界定每个独立细胞轮廓的一系列空间坐标点,形成多边形以表示细胞的边界。
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
head(GetTissueCoordinates(vizgen.obj[["s2r1"]][["segmentation"]]))

##          x        y                                    cell
## 1 644.0774 4589.022 149164679103246548309819743981609972453
## 2 643.9694 4589.022 149164679103246548309819743981609972453
## 3 643.8614 4589.022 149164679103246548309819743981609972453
## 4 643.7642 4588.924 149164679103246548309819743981609972453
## 5 643.7534 4588.914 149164679103246548309819743981609972453
## 6 643.6454 4588.914 149164679103246548309819743981609972453
  • 分子定位信息:记录了在多重单分子荧光原位杂交(smFISH)实验过程中发现的每一个分子的空间位置。
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
head(FetchData(vizgen.obj[["s2r1"]][["molecules"]], vars = "Chrm1"))

##          x        y molecule
## 1 577.3373 4205.977    Chrm1
## 2 600.0218 3917.781    Chrm1
## 3 508.2736 3934.063    Chrm1
## 4 630.7590 3948.586    Chrm1
## 5 635.1143 3969.567    Chrm1
## 6 582.7043 4021.577    Chrm1

预处理和无监督分析

我们首先进行常规的无监督聚类分析,将数据集初步处理为单细胞RNA测序(scRNA-seq)实验。在标准化过程中,我们采用了基于SCTransform的方法,并对默认的裁剪参数进行了微调,以减少smFISH实验中偶尔出现的异常值对我们分析结果的干扰。完成标准化后,我们便可以进行数据的降维处理和聚类分析。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
vizgen.obj <- SCTransform(vizgen.obj, assay = "Vizgen", clip.range = c(-10, 10))
vizgen.obj <- RunPCA(vizgen.obj, npcs = 30, features = rownames(vizgen.obj))
vizgen.obj <- RunUMAP(vizgen.obj, dims = 1:30)
vizgen.obj <- FindNeighbors(vizgen.obj, reduction = "pca", dims = 1:30)
vizgen.obj <- FindClusters(vizgen.obj, resolution = 0.3)

然后,我们可以在 UMAP 空间(使用 DimPlot())中可视化聚类结果,或者使用 ImageDimPlot() 覆盖在图像上。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
DimPlot(vizgen.obj, reduction = "umap")
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
ImageDimPlot(vizgen.obj, fov = "s2r1", cols = "polychrome", axes = TRUE)

由于在一起查看单个簇时很难可视化它们的空间定位模式,因此我们可以突出显示属于特定簇的所有细胞:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
p1 <- ImageDimPlot(vizgen.obj, fov = "s2r1", cols = "red", cells = WhichCells(vizgen.obj, idents = 1))
p2 <- ImageDimPlot(vizgen.obj, fov = "s2r1", cols = "red", cells = WhichCells(vizgen.obj, idents = 15))
p1 + p2

我们能够识别每个独立聚类的特征标志物,并展示它们在空间上的表达分布。通过使用ImageFeaturePlot()函数,我们可以根据单个基因的表达量来对细胞进行着色,这与FeaturePlot()函数的作用相似,都是为了在二维平面上展示基因表达的分布情况。考虑到MERFISH技术能够对单个分子进行成像,我们还能够在图像上直接观察到每个分子的具体位置。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
p1 <- ImageFeaturePlot(vizgen.obj, features = "Slc17a7")
p2 <- ImageDimPlot(vizgen.obj, molecules = "Slc17a7", nmols = 10000, alpha = 0.3, mols.cols = "red")
p1 + p2

请注意,我们可以通过设置nmols参数来降低图中展示的分子数量,这样可以避免因分子过多而导致的重叠问题。此外,您还可以调整mols.size(分子大小)、mols.cols(分子颜色)和mols.alpha(分子透明度)等参数,以进一步优化图表的展示效果。

在图表上绘制分子对于展示同一图表中多个基因的共表达情况尤为有用。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
p1 <- ImageDimPlot(vizgen.obj, fov = "s2r1", alpha = 0.3, molecules = c("Slc17a7", "Olig1"), nmols = 10000)
markers.14 <- FindMarkers(vizgen.obj, ident.1 = "14")
p2 <- ImageDimPlot(vizgen.obj, fov = "s2r1", alpha = 0.3, molecules = rownames(markers.14)[1:4],
    nmols = 10000)
p1 + p2

最新版的Seurat空间分析框架提供了两种显示细胞的方式:

  1. 一种是将细胞作为单独的点来处理,另一种是展示细胞的边界(即细胞的轮廓)。默认情况下,Seurat不显示细胞的轮廓,而是将每个细胞简化为一个点(称为“中心点”),这样做可以提高在大面积区域绘图时的效率,因为在这些区域中,细胞的边界细节往往难以辨认。
  2. 我们可以通过放大来聚焦组织的特定区域,从而形成一个新的观察视野。比如,我们可以放大到包含海马体的区域进行观察。放大后,我们可以通过设置DefaultBoundary()来展示细胞的边界。此外,为了提高绘图的效率,我们还可以选择“简化”这些细胞边界,即减少每个多边形的边数。
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
# create a Crop
cropped.coords <- Crop(vizgen.obj[["s2r1"]], x = c(1750, 3000), y = c(3750, 5250), coords = "plot")
# set a new field of view (fov)
vizgen.obj[["hippo"]] <- cropped.coords

# visualize FOV using default settings (no cell boundaries)
p1 <- ImageDimPlot(vizgen.obj, fov = "hippo", axes = TRUE, size = 0.7, border.color = "white", cols = "polychrome",
    coord.fixed = FALSE)

# visualize FOV with full cell segmentations
DefaultBoundary(vizgen.obj[["hippo"]]) <- "segmentation"
p2 <- ImageDimPlot(vizgen.obj, fov = "hippo", axes = TRUE, border.color = "white", border.size = 0.1,
    cols = "polychrome", coord.fixed = FALSE)

# simplify cell segmentations
vizgen.obj[["hippo"]][["simplified.segmentations"]] <- Simplify(coords = vizgen.obj[["hippo"]][["segmentation"]],
    tol = 3)
DefaultBoundary(vizgen.obj[["hippo"]]) <- "simplified.segmentations"

# visualize FOV with simplified cell segmentations
DefaultBoundary(vizgen.obj[["hippo"]]) <- "simplified.segmentations"
p3 <- ImageDimPlot(vizgen.obj, fov = "hippo", axes = TRUE, border.color = "white", border.size = 0.1,
    cols = "polychrome", coord.fixed = FALSE)

p1 + p2 + p3

我们可以在放大后以更高分辨率可视化绘制的单个分子

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
# Since there is nothing behind the segmentations, alpha will slightly mute colors
ImageDimPlot(vizgen.obj, fov = "hippo", molecules = rownames(markers.14)[1:4], cols = "polychrome",
    mols.size = 1, alpha = 0.5, mols.cols = c("red", "blue", "yellow", "green"))
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2024-06-20,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 冷冻工厂 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
5.JUC线程高级-创建线程的第三种方式实现 Callable接口
执行Callable方式,需要FutureTask 实现类的支持,用于接收运算结果。FutureTask 是 Future 接口的实现类。
用户1212940
2022/04/13
1780
5.JUC线程高级-创建线程的第三种方式实现 Callable接口
6.实现 Callable 接口
6.实现 Callable 接口 前言 本篇章来介绍一下创建线程的第三种方式,其中创建线程一共有四种方式: 继承 Thread 类 实现 Runnable 接口 实现 Callable 接口 使用线程池的方式 那么下面我们来介绍一下 实现 Callable 接口的方式。 Callable 接口 - Java 5.0 在 java.util.concurrent 提供了一个新的创建执行线程的方式:Callable 接口 - Callable 接口类似于 Runnable,两者都是为那些其实例可能被另一个线程
Devops海洋的渔夫
2022/03/23
6060
6.实现 Callable 接口
java 多线程Thread、Runnable和Callable的区别和用法
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/126573.html原文链接:https://javaforall.cn
全栈程序员站长
2022/07/23
2540
Java多线程实现的几种方式
多进程是计算机中的一个重要概念,通常一个任务称为一个进程,比如浏览网页、播放音乐都是一个进程。
benym
2022/07/14
3810
进程和线程
进程是指一个内存中运行的应用程序,每个进程都有自己独立的一块内存空间,一个进程中可以启动多个线程。 线程是比进程更小的执行单位,它是在一个进程中独立的控制流,一个进程可以启动多个线程,每条线程并行执行不同的任务。
joshua317
2021/09/28
6900
【并发那些事】创建线程的三种方式
创建线程可以说是并发知识中最基础的操作了,JDK 提供的创建线程的方式,如果不包括通过线程池的话,目前有三种形式,它们分别是通过继承 Thread 类,通过实现 Runable 接口,通过 FutureTask。如下图所示
KIWI
2020/04/08
3510
创建线程都有哪些方式?— Callable篇
相信大家回答这个问题没什么难度吧?通常问完创建方式,那么接下来就是问「1、2」跟「3」创建方式的不同了,只要说出「3」有返回值基本这个问题就过了,不管是出于好奇还是疑惑,我们今天来会会这个Callable。
niceyoo
2020/07/26
8060
多线程之jdk 5.0新增的两种创建方式
创建线程的方式三:实现callable接口 -------jdk5.0新增 返回结果并且可能抛出异常的任务。实现者定义了一个不带任何参数的叫做 call 的方法。 Callable 接口类似于 Runnable,两者都是为那些其实例可能被另一个线程执行的类设计的。但是 Runnable 不会返回结果,并且无法抛出经过检查的异常。 接口 Executor 执行已提交的 Runnable 任务的对象。此接口提供一种将任务提交与每个任务将如何运行的机制(包括线程使用的细节、调度等)分离开来的方法。通常使用 Executor 而不是显式地创建线程。例如,可能会使用以下方法,而不是为一组任务中的每个任务调用 new Thread(new(RunnableTask())).start():
暴躁的程序猿
2022/03/24
2080
多线程之jdk 5.0新增的两种创建方式
JUC前言:一、volatile关键字与内存可见性二、原子性三、锁分段机制四、闭锁五、创建线程的方式 --- 实现Callable接口六、Lock同步锁七、等待唤醒机制八、ReadWriterLock
在Java中,线程部分是一个重点,本篇文章说的JUC也是关于线程的。JUC就是java.util .concurrent工具包的简称。这是一个处理线程的工具包,JDK 1.5开始出现的。下面一起来看看它怎么使用。
贪挽懒月
2018/12/27
7810
详解多线程启动涉及的知识点
如果一个类继承Thread,则不适合资源共享。但是如果实现了Runable接口的话,则很容易地实现资源共享。实现Runnable接口比继承Thread类所具有的优势:
BUG弄潮儿
2022/06/30
2060
详解多线程启动涉及的知识点
Java面试之创建线程的三种方法及其区别
然后,调用Thread类的构造函数创建Thread实例并调用start()方法启动线程:
leon公众号精选
2022/04/27
2830
Java面试之创建线程的三种方法及其区别
JAVA代码实现多线程的方式总结
1) 第一种方式: a. 类 继承 java.lang.Thread类,同时覆盖run方法 注意:线程任务定义在run方法中 b. 创建线程对象: MyThread t = new MyThread(); c. 开启线程:利用 start开启线程,jvm执行线程时会自动的 调用run
猫头虎
2024/04/07
1580
创建线程的三种方式
1)继承Thread类,重写run方法 2)实现Runnable接口创建线程 3)使用Callable和Future创建线程
名字是乱打的
2022/05/13
2700
Java多线程之Callable和Future
本篇说明的是Callable和Future,它俩很有意思的,一个产生结果,一个拿到结果。
Java团长
2018/08/06
6370
【多线程】JUC的常见类,Callable接口,ReentranLock,Semaphore,CountDownLatch
所以创建一个线程,希望它给你返回一个结果,那么使用 Callable 更加方便一些
椰椰椰耶
2024/09/20
890
【多线程】JUC的常见类,Callable接口,ReentranLock,Semaphore,CountDownLatch
面试官:除了继承Thread类和实现Runnable接口,你知道使用Callable接口的方式来创建线程吗?
终有救赎
2023/10/16
2110
面试官:除了继承Thread类和实现Runnable接口,你知道使用Callable接口的方式来创建线程吗?
多线程(一)-两种创建线程的方式+实现Callable接口方式
​ 继承Thread必须重写run方法,(具体业务执行方法,需要执行的业务方法,定义在此方法中),注意此方法是线程启动后线程自动调用的;
化羽羽
2022/10/28
4450
Java并发编程之Future和FutureTask
搞过Java或者客户端Android开发的都知道,创建线程的2种方式,一种是直接继承Thread,另外一种就是实现Runnable接口。不过,这2种方式都有一个缺陷,就是在执行完任务之后无法获取执行结果。
xiangzhihong
2022/11/30
3780
JAVA多线程高并发学习笔记(三)——Callable、Future和FutureTask
为什么要是用Callable和Future Runnable的局限性 Executor采用Runnable作为基本的表达形式,虽然Runnable的run方法能够写入日志,写入文件,写入数据库等操作,但是它不能返回一个值,或者抛出一个受检查的异常,有些需要返回值的需求就不能满足了。 能够取消 Executor中的任务有四个状态:创建,提交,开始和完成。如果说有些任务执行时间比较长,希望能够取消该任务,Executor中的任务在未开始前是可以取消的,如果已经开始了,只能通过中断的方式来取消。如果使用Calla
Janti
2018/04/10
9620
JAVA多线程高并发学习笔记(三)——Callable、Future和FutureTask
【80期】说出Java创建线程的三种方式及对比
上述代码中Thread.currentThread()方法返回当前正在执行的线程对象。GetName()方法返回调用该方法的线程的名字。
良月柒
2020/11/06
3880
【80期】说出Java创建线程的三种方式及对比
推荐阅读
相关推荐
5.JUC线程高级-创建线程的第三种方式实现 Callable接口
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验