单细胞系列教程:PCA和归一化理论(七)

1. 学习目标

  • 讨论为什么归一化计数对于细胞之间的准确比较是必要的
  • 解释如何通过主成分分析 (PCA) 评估细胞之间的相似性

在获得高质量单细胞后,scRNA-seq分析工作流程的下一步是执行聚类。聚类的目标是将不同的细胞类型分成独特的细胞簇。为了进行聚类,确定了细胞间表达差异最大的基因。然后,使用这些基因来确定哪些相关基因组是造成细胞间表达差异最大的原因。

2. 计数归一化

第一个是计数归一化,这对于准确比较细胞(或样本)之间的基因表达至关重要。除了许多其他因素之外,每个基因的映射读数计数与RNA的表达成正比。归一化是缩放原始计数值的过程。以这种方式,细胞之间或细胞内的表达水平更具可比性。

归一化过程中经常考虑的主要因素有:

  • 测序深度

考虑测序深度对于比较细胞之间的基因表达是必要的。在下面的示例中,每个基因在细胞 2 中的表达似乎都增加了一倍,但这是细胞 2 具有两倍测序深度的结果。

scRNA-seq 中的每个细胞都有不同数量的与其相关的读取。因此,为了准确比较细胞之间的表达,有必要对测序深度进行归一化。

  • 基因长度

考虑基因长度对于比较同一细胞内不同基因之间的表达是必要的。映射到较长基因的读数的数量似乎与表达更高的较短基因具有相同的计数。

scRNA-seq分析中,将比较细胞内不同基因的表达以对细胞进行聚类。如果使用基于 3' 或 5' 液滴的方法,基因的长度不会影响分析,因为仅对转录本的 5' 或 3' 端进行测序。但是,如果使用全长测序,则应考虑转录本长度。

3. PCA

主成分分析 (PCA) 是一种用于强调变化和相似性的技术,并在数据集中显示出强烈的模式;它是用于“降维”的方法之一。本课中简要介绍PCA,强烈建议您浏览StatQuest 的视频以获得更全面的解释。

  • 一个简单的例子

假设您已经量化了两个样本(或细胞)中四个基因的表达,您可以绘制这些基因的表达值,其中一个样本代表 x 轴,另一个样本代表 y 轴,如下所示:

您可以在表示最大变化的方向上通过数据绘制一条线,在本例中位于对角线上。数据集中的最大变异发生在构成这条线的两个端点的基因之间。

基因在线上和线下有所不同。可以在数据中绘制另一条线,表示数据中第二大的变化量,因为该图是二维的(2 个轴)。

每行末端附近的基因是变异最大的基因;从数学上讲,这些基因对线的方向影响最大。

例如,Gene C 值的微小变化会极大地改变较长线的方向,而 Gene A 或 Gene D 的微小变化对其影响不大。

还可以旋转整个图,并查看代表变化的线条从左到右和上下。看到数据中的大部分变化是从左到右(较长的线),数据中第二大的变化是上下(较短的线)。您现在可以将这些线视为表示变化的轴。这些轴本质上是“主成分”,PC1 代表数据中最大的变化,PC2 代表数据中第二大的变化。

现在,如果有三个样本/细胞,那么将有一个额外的方向,可以在其中进行变化。因此,如果有 N 个样本/细胞,将有 N 个变化方向或 N 个主成分(PCs)!计算完这些 PC 后,处理数据集中变化最大的 PC 被指定为 PC1,下一个被指定为 PC2,以此类推。

一旦确定了数据集的 PC,必须弄清楚每个样本/单元如何重新适应该上下文,能够以直观的方式可视化相似性/不相似性。这里的问题是“基于 sample_X 中的基因表达,给定 PC 的 sample_X 得分是多少?”。这是降低维度的实际步骤,因为最终 PCA 图上绘制每个样本/单元格的 PC 分数。

为所有样本-PC 对计算 PC 分数,如下面的步骤和示意图中所述:

(1) 首先,根据每个基因对 PC 的影响程度,为每个基因分配一个“影响”分数。对给定 PC 没有任何影响的基因得分接近于零,而影响更大的基因得分更高。 PC 线末端的基因将产生更大的影响,因此它们将获得更大的分数,但符号相反。

(2) 确定影响后,使用以下等式计算每个样本的分数:

Sample1 PC1 score = (read count * influence) + ... for all genes

对于 2 个样本示例,以下是计算分数的方式:

## Sample1
PC1 score = (4 * -2) + (1 * -10) + (8 * 8) + (5 * 1) = 51
PC2 score = (4 * 0.5) + (1 * 1) + (8 * -5) + (5 * 6) = -7

## Sample2
PC1 score = (5 * -2) + (4 * -10) + (8 * 8) + (7 * 1) = 21
PC2 score = (5 * 0.5) + (4 * 1) + (8 * -5) + (7 * 6) = 8.5

这是前两个步骤的示意图:

(3) 一旦为所有 PC 计算了这些分数,就可以将它们绘制在一个简单的散点图上。下面是此处示例的图,从 2D 矩阵到 2D 图:

  • scRNA-seq 例子

假设您正在处理一个包含 12,000 个细胞的单细胞 RNA-seq 数据集,并且您已经量化了 20,000 个基因的表达。

计算出 PC 分数后,您将看到一个 12,000 x 12,000 的矩阵,它表示有关所有细胞中相对基因表达的信息。您可以选择 PC1 和 PC2 列并以 2D 方式绘制。

您还可以将前 40 台 PC 的 PC 分数用于聚类、标记识别等下游分析,因为这些代表了数据中的大部分变化。

注意:对于具有大量样本或单元格的数据集,通常仅绘制每个样本/单元格的 PC1 和 PC2 分数,或用于可视化。由于这些 PC 解释了数据集中的最大变化,因此期望彼此更相似的样本/细胞将与 PC1 和 PC2 聚集在一起。请参阅下面的真实示例:

本文转载于网络 如有侵权请联系删除

相关文章

  • 3.Mysql 主要数据结构

    BulkInsert 在批量插入数据时,并非直接将key写入B-tree,而是写入红黑树,当红黑树达到上限时,将所有的key写入磁盘。写入的key流是已经排序好的,所以写入非常快缓存 1.Keycache 所有B-Tree索引的共享缓存,使用hash和反转链表来快速定位最近使用的blocks,并快速特定表的更新项。位于 mysys/mf_keycash.c 2.Recordcache 这用于快速扫描表中的所有记录。位于 mysys/mf_iocash.c and isam/_cash.c 3.TableCache 它保存最近使用的表位于 sql/sql_base.cc 4.PrivilegeCache 为了允许在数据库之间进行快速更改,将为每个用户/数据库组合缓存上次使用的权限。 位于sql/sql_acl.cc 5.HeapTableCache groupby或distinct缓存找到的行,放入到heaptable中, 6.JoinBufferCache 连接缓存,由 join_buffer_size变量定义大小,该缓存仅用于jointype是ALL或INDEX,不会为第一个非常量表

  • 数据结构算法操作试题(C++/Python)——有效的数独

    1.题目leetcode链接:https://leetcode-cn.com/problems/valid-sudoku/submissions/ 2.解答python:272ms,11.9mbclassSolution(object): defisValidSudoku(self,board): """ :typeboard:List[List[str]] :rtype:bool """ foriinrange(9): ifnotself.isvalidList(board[i]):returnFalse ifnotself.isvalidList([j[i]forjinboard]):returnFalse indexList=[0,3,6] ifi%3==0: forjinindexList: numsList=[] numsList+=board[i][j:j+3] numsList+=board[i+1][j:j+3] numsList+=board[i+2][j:j+3] printnumsList ifnotse

  • Knocknock 登陆韩国 Kakao 公链 Klaytn

    2019年3月19日,由韩国社交巨头Kakao的区块链子公司GroundX负责开发的全球公链平台Klaytn邀请合作伙伴参与KakaoKlaytnPartnersDay。微位科技作为合作伙伴受邀参与并发布了在Klaytn上的DAppKnocknock諾客。2018年3月,Kakao曾首次公布其设立区块链子公司GroundX的计划,当时并表示未来会将基于区块链的服务于Kakao现有的互联网产品(如KakaoTalk:韩国最大的社交软件)。去年第三季度,GroundX推出了全球公链平台Klaytn的测试网络。Klaytn区块链将采用共识节点(CN)和游侠节点(RN)的混合方式概念来实现可扩展性和透明性,据称,GroundX声称测试网络中的区块传播间隔已减少到每秒不到一秒,并且每秒可提供高达1,500次的吞吐量。这为DApp(DecentralizedApplication分布式应用)的运行奠定了技术基础。Klaytn在去年的12月12日公布了第一批主打DApp,微位科技的Knocknock成为了Klaytn首推的DApp。Klaytn在官方介绍中称,“Knocknock为具有行业透明度和可

  • 【转】闭包会造成内存泄漏吗?

    前言   在谈内存泄漏这个问题之前先看看JavaScript的垃圾收集机制,JavaScript具有自动垃圾收集机制,就是找出那些不再继续使用的变量,然后释放其占用的内存。为此,垃圾收集器会按照固定的时间间隔(或代码执行中预定的收集时间)。常用的的方法有两种,即标记清楚和引用计数。   标记清除   JavaScript中最常用的垃圾收集方式是标记清除(mark-and-sweep)。垃圾收集器在运行的时候会给存储在内存中的所有变量都加上标记(可以使用任何标记方式)。然后,它会去掉环境中的变量以及被环境中的变量引用的变量的标记。而在此之后再被加上标记的变量将被视为准备删除的变量,原因是环境中的变量已经无法访问到这些变量了。最后,垃圾收集器完成内存清除工作,销毁那些带标记的值并回收它们所占用的内存空间。   引用计数   引用计数(referencecounting)的含义是跟踪记录每个值被引用的次数。引用计数的含义是跟踪记录每个值被引用的次数。当声明了一个变量并将一个引用类型值赋给该变量时,则这个值的引用次数就是1。如果同一个值又被赋给另一个变量,则该值的引用次数加1。相反,如果包含

  • 【转】 jquery easyui Tab 引入页面的问题

    原地址:http://blog.csdn.net/superdog007/article/details/8225518  jQueryEasyui的tabs插件有两种方式加载某个tab(标签页)上的内容:“href远程请求”和“content本地内容”,本文就两种方式的优缺点进行简单分析和思考。 两者特点: href方式加载数据的特点: 被加载的页面只有body元素内部的内容才会被加载,也就是jQuery的ajax请求的只是html片段。 加载远程url时有遮罩效果,也就是“等待中……”效果,用户体验较好。 当加载的页面布局较为复杂,或者有较多的js脚本需要运行的时候,编码往往就需要谨慎了,容易出问题,后面会详细谈。 content方式加载数据的特点: 比较灵活,你可以在脚本里面拼写html代码,然后赋值给tab的content属性,不过这种写法会使得代码易读性变差。 可以把iframe赋给content,把一个iframe嵌入也就没有什么不能完成的了。 使用iframe会造成客户端js重复加载,浪费资源,比如说你主页面要引用easyui的库,你的iframe也要引用

  • luoguP1114 “非常男女”计划 [前缀和]

    题目描述 近来,初一年的XXX小朋友致力于研究班上同学的配对问题(别想太多,仅是舞伴),通过各种推理和实验,他掌握了大量的实战经验。例如,据他观察,身高相近的人似乎比较合得来。 万圣节来临之际,XXX准备在学校策划一次大型的“非常男女”配对活动。对于这次活动的参与者,XXX有自己独特的选择方式。他希望能选择男女人数相等且身高都很接近的一些人。这种选择方式实现起来很简单。他让学校的所有人按照身高排成一排,然后从中选出连续的若干个人,使得这些人中男女人数相等。为了使活动更热闹,XXX当然希望他能选出的人越多越好。请编写程序告诉他,他最多可以选出多少人来。 输入格式 第一行有一个正整数nn,代表学校的人数。n\le100000n≤100000 第二行有nn个用空格隔开的数,这些数只能是00或11,其中,00代表一个女生,11代表一个男生 输出格式 输出一个非负整数。这个数表示在输入数据中最长的一段男女人数相等的子序列长度。 如果不存在男女人数相等的子序列,请输出00。 输入输出样例 输入#1复制 9 010001100 复制 输出#1复制 6Solution虽然这题本身不是太

  • TOP 10 BEST LINUX GAMES RELEASED IN 2016

    GamingonLinux usedtobeaveryrarephrase.Butsincethearrivalof SteamonLinux,theLinuxgamingcommunityisallchargedupbecauseofthegamesbeingnativelydevelopedforLinuxinsteadofbeingdependentonthird-partyapplicationslikeWineorPlayOnLinux. Thereare over1500gamesforLinuxavailableonSteam itself.Butyoudon’tneedtogothroughallofthemasIhavelisted bestLinuxgamesoftheyear2016here.Checkoutthislist. BESTLINUXGAMESRELEASEDIN2016 Beforewegoonseeingthegames,letmemakeafewthingsclear.WhenIsay,relea

  • 弹性盒子

    弹性盒子的作用不管是电脑端还是移动端都很普遍了,代替了浮动和定位对div的操作,在某方面来说还是机器方便的 设置方式 在父元素盒子中设置  display:flex 在弹性盒子中主轴是X轴,交叉轴是Y轴      设置主轴方向:  flex-direction:row  默认主轴从左到右        column 设置主轴从上到下         row-reverse 设置主轴从右至左(内容翻转) flex-wrap:norwoap 默认不换行     wrap:设置子项换行     wrap-reverse:逆向换行,从后至前 justify-content:flex-end:从主轴结束的位置开始排序        flex-start:从主轴开始位置开始排序         center:始终是居中位置】         space-around:设置子项平均分布         space-between:设置子项左右紧贴,中间内容居中 aling-items(单行): fle

  • 推荐,慕课网好课,仿阿里系优酷网-企业级Go改造PHP项目踩坑避坑指北

    互联网早期,企业为实现网站快速上线与变现盈利,不少网站基于PHP构建,如:阿里系的优酷网、Google的YouTube等,但随业务发展,后劲不足,出现性能等问题。当下,5G引领视频技术风向标,故本课以“优酷网”为蓝本,先基于PHP构建“慕优酷网”,后进行Go改造。捞干的讲:课程赠送从0到1的PHP源码。核心内容是:精讲从1到N的Go改造过程如何踩坑避坑,掌握三大性能利器:Redis、RabbitMQ、Elasticsearch,改造完毕还有压测对比,看得见的性能提升。还原真实项目架构演进、代码重构迭代过程。源于真实阿里项目,让你的能力接轨于企业刚需 https://coding.imooc.com/class/443.html?mc_marking=81b432eb6d3a2e8880839014a285d2f3&mc_channel=banner

  • win8 Pro 64位在 UEFI模式下Ghost系统 备份 恢复

    一:在win8安装U盘中  1.新建“Ghost”文件夹 2.将下载的Ghost64.exe文件拷贝到文件夹      二:启动的时候按下F12选择HDDUSB 1.Windows安装程序,选择“下一步” 2.在屏幕左下角选择“repairthecomputer” 3. 选择troubleshuting 4.选择advanced  5.选择CMDcommand 6.输入e: 7.输入dir 8.输入cdGhost 9.输入dir 10.可以看到Ghost64.exe文件 11.输入 Ghost64.exe             三备份操作 此处操作 选择菜单  Local(本机)--Partition(分区)--ToImage(到镜像) 通俗一点说就是1-2-2 先选中 1 再选取弹出选项 2 再选取弹出选项 2  5选中后回车将出现如图三  选择硬

  • 正确使用 Volatile 变量2

    模式#3:独立观察(independentobservation) 安全使用volatile的另一种简单模式是:定期“发布” 观察结果供程序内部使用。例如,假设有一种环境传感器能够感觉环境温度。一个后台线程可能会每隔几秒读取一次该传感器,并更新包含当前文档的 volatile变量。然后,其他线程可以读取这个变量,从而随时能够看到最新的温度值。 使用该模式的另一种应用程序就是收集程序的统计信息。清单4 展示了身份验证机制如何记忆最近一次登录的用户的名字。将反复使用 lastUser 引用来发布值,以供程序的其他部分使用。 清单4.将volatile变量用于多个独立观察结果的发布 1 2 3 4 5 6 7 8 9 10 11 12 13 publicclassUserManager{     public volatileStringlastUser;       public booleanauthentica

  • Swift - 属性

    属性的意义:将值和对象、结构体关联上 储存属性 将常量、变量存储为实例对象的一部分 structPerson{ varname:String=""//存储属性(变量) letage=10//存储属性(常量) }复制 计算属性 本质上是方法,主要来用调用、计算存储属性 structPerson{ varinfo:String{//计算属性 get{ self.name+"年龄"+String(self.age) } set{ ifnewValue=="未成年"{ self.age=15 }else{ self.age=20 } } } }复制 计算属性的set方法中,可以获取即将赋值的值newValue  属性观察器 存储属性的赋值操作可以进行监听,有点类似于OC的set方法 willSet:监听赋值之前,新值可以通过newValue获取 didSet:监听赋值之后,旧值可以通过oldValue获取 structPerson{ varage=10{//存储属性 willSet{ print("还没开始赋值,即将赋值中...age:",age,"newValue:",newVa

  • openlayers6聚合图(附源码下载)

    前言 之前写过一篇openlayers4版本的地图聚合图文章,但是由于是封装一层js代码写的,很多初学者看起来比较有点吃力,所以本篇文章重新写一篇地图热力图文章,直接基于最新版本openlayers6写的,纯粹html+js+css形式,没有任何封装。 内容概览 1.基于openlayers6实现地图聚合图效果2.源代码demo下载 效果图如下: 大概实现思路如下:读取聚合图模拟数据源json,构造openlayers聚合图数据源features,然后创建聚合图图层(核心数据源类Cluster),设置Cluster的初始化一些参数值,参数详细说明自行看openlayers官网文档api。 部分核心代码,完整的见源码demo下载 import{Map,View}from'ol'; importXYZfrom'ol/source/XYZ'; import{CircleasCircleStyle,Fill,Stroke,Style,Text}from'ol/style'; import{HeatmapasHeatmapLayer,TileasTileLayer}fr

  • Python_DL_July_深度学习_10_深度学习与各种迁移学习应用

    深度学习10(上)深度学习与各种迁移学习应用

  • 内置函数 集锦

    1#input() 2#print() 3#int 4#float 5#dict(a=1,b=2) 6#list('123') 7#set() 8#tuple() 9#bool 10#type 11#id 12#len 13print(bool('')) 14print(bool(None)) 15print(bool([])) 16print(bool({})) 17print(bool(())) 18print(bool(0)) 19 20sum([1,2,3,4,5]) 21max() 22min() 23print(round('1.999',2))#保留几位小数 24print(divmod(10,5))#取余数 25print(globals())#把当前文件中的所有的变量取出来 26print(locals()) 27 28defabc(): 29print(locals())#取函数里面的所有的局部变量 30print(globals())#取整个python文件里面的所有变量 31abc() 32 33print(chr(65))#ascii码对应的字符 34prin

  • 用nRF52的RTC实现万年历

     nRF52系列芯片内部有3个RTC,其中RTC0是给协议栈softdevice用,RTC1分配给Apptimer用,剩下的RTC2可以用来实现万年历功能。  代码基于SDK15.0,在BLE_APP_UART例程上进行添加和修改: 1)  在工程Application目录添加ble_calendar.c并包含对应头文件和目录; 2)  详细代码参看:https://pan.baidu.com/s/1BlTMcz5qnfZ3SjscczoOlw,提取码:k97k 3)  用nrfToolbox->UART工具编译三条命令,分别发‘s’ ’g’  ‘u’  4)  用putty和RTT都可以查看打印结果 RTC寄存器和分频系数设置方法:    Example: 计算COUNTERfrequency8Hz(125mscounterperiod) PRESCALER=round(32.768kHz/8Hz)–1=4095 fRT

  • C++函数模板特化,类模板特化

    一、模版与特化的概念 1.函数模版与类模版 C++中模板分为函数模板和类模板 函数模板:是一种抽象函数定义,它代表一类同构函数。类模板:是一种更高层次的抽象的类定义。 2.特化的概念 所谓特化,就是将泛型的东西搞得具体化一些,从字面上来解释,就是为已有的模板参数进行一些使其特殊化的指定,使得以前不受任何约束的模板参数,或受到特定的修饰(例如const或者摇身一变成为了指针之类的东东,甚至是经过别的模板类包装之后的模板类型)或完全被指定了下来。 二、模板特化的分类 针对特化的对象不同,分为两类:函数模板的特化和类模板的特化 1.函数模板的特化 当函数模板需要对某些类型进行特化处理,称为函数模板的特化。 2.类模板的特化 当类模板内需要对某些类型进行特别处理时,使用类模板的特化。 3.特化整体上分为全特化和偏特化 (1)全特化 就是模板中模板参数全被指定为确定的类型。 全特化也就是定义了一个全新的类型,全特化的类中的函数可以与模板类不一样。 (2)偏特化 就是模板中的模板参数没有被全部确定,需要编译器在编译时进行确定。 全特化的标志就是产生出完全确定的东西,而不是还需要在编译期间去搜

  • 第一次作业:深度学习基础

    PartⅠ视频学习心得及问题总结 1.绪论 1.1从专家系统到机器学习 1.1.1人工智能的发展经历了三个阶段:推理期、知识期、学习期。 知识工程/专家系统——根据专家定义的知识与经验,进行推理和判断,从而模拟人类专家的决策过程来解决问题。 机器学习——从数据中自动的提取出知识或模式。 1.1.2专家系统vs机器学习 专家系统 机器学习 基于手工设计规则建立专家系统 基于数据自动学习 结果容易解释 减少人工繁杂工作,但结果可能不易解释 系统构建费时费力 提高信息处理的效率,且准确率较高 依赖于专家主观经验,难以保证一致性和准确性 来源于真实数据,减少人工规则主观性,可信度高 1.2从传统机器学习到深度学习 1.2.1传统机器学习 在实际应用中,特征比分类器更重要。原始数据经过数据预处理、特征提取、特征选择,最后经过分类预测识别得到最后的结果。在传统的机器学习中,人工会去手动的设计特征。 1.2.2深度学习 在深度学习中,首先选择深度学习的模型以及模型的参数,然后把收集到的数据和选择好的模型交给计算机,让计算机去优化这个深度模型中的参数。在这

  • Golang 之 key-value LevelDB

    时常会在应用中用到数据库功能,象Key-Value性质的。直接搬个Redis,Mysql嫌大,好在有LevelDB,直接编进应用中。 有关什么是LevelDB以及LevelDB的特性,可Google之,我们看看如何用。 先要 gogetgithub.com/syndtr/goleveldb/leveldb复制 然后在文件中import进来。 1.打开数据库 db,err=leveldb.OpenFile("./db",nil)复制 if(err!=nil){panic(err)}复制 如果这里如果有错,直接报了。   2.然后,读用db.Get,写用db.Put。 3.代码中的一小段。 packagemain import( "github.com/syndtr/goleveldb/leveldb" "fmt" "strconv" ) vardb*leveldb.DB constID_FIELD="id" funcinit(){ varerrerror db,err=leveldb.OpenFile("./db",nil) if(err!=nil){ pan

  • 基于ACE的TAO开发---一个简单的入门实例-----VS2008(一)

    万事开头难,不管做什么事最开始总是最困难的,一旦上手了就好了。 这也是我自己学习corba编程的一点经验和心得。下面的例子主要是保证读者跟着走能立马看到效果。 1.机器上的TAO是实现已经装好的开发版。环境变量那些都已经配好。 2.新建一个解决方案,添加一个Win32项目,类型可以选静态lib。在源文件中添加一个idl文件,如下图 3.配置编译选项及输出。还是先直接上图,让大家看得更清楚。 a.将编译工具设置为“自定义生成工具” b.在自定义生成步骤中定义好:命令行,输出 4.编译 5.看编译成果。 框出来的部分就是新生成的文件。 后续http://www.cnblogs.com/gig886/p/6599407.html  

  • 2018-2019-2 网络对抗技术 20165228 Exp5 MSF基础应用

    2018-2019-2网络对抗技术20165228Exp5MSF基础应用 exploit选取 主动攻击:ms17_010_eternalblue(唯一) 浏览器攻击:ms05_054_onload(唯一) 客户端攻击:adobe_pdf_embedded_exe(唯一) 辅助模块:telnet_version(唯一) 问题思考 exploit:记得老师上课的时候说exploit是把payload“背”过去。。。不太明白“背”是什么意思,我个人理解应该就是把配置好的东西送至靶机的一种攻击模块 payload:用来攻击的代码、程序等 encode:根据之前的实验来看,它的作用应该是使payload变形,从而实现免杀的目的 实验内容 任务一:ms17_010_eternalblue主动攻击实践(靶机:win7专业版) Description: ThismoduleisaportoftheEquationGroupETERNALBLUEexploit, partoftheFuzzBunchtoolkitreleasedbyShadowBrokers.Thereisa bufferoverf

相关推荐

推荐阅读