BAM索引损坏时,为什么文件仍可能看似正常
BAM能从头读取,只证明部分顺序读取路径可用。区域跳转还依赖坐标排序和匹配索引;应分别验证主文件、索引、参考序列与目标区间。
一个BAM文件打开后,染色体开头能看见比对轨道;输入某个基因坐标,浏览器却显示空白或报索引错误。最容易下的结论是文件坏了,或该区域没有数据。其实这两个结论都太快:顺序读取、索引定位和生物学覆盖是三件不同的事。
为什么部分轨道会先显示出来
许多工具载入BAM时会先读取文件头、参考序列字典和前部记录,用来确认格式并建立界面。这个过程可能只需顺序解析一小段数据。只要文件开头仍可读,浏览器就可能画出部分轨道或显示样本名称。
跳转到远处坐标时,工具通常不会从头扫描整个BAM。它会查询配套的BAI或CSI,找到目标区间可能对应的压缩数据块,再直接移动到相应位置。主文件可顺序读取、索引却错配时,前部显示正常而局部跳转失败正是合理结果。
空白也不一定表示索引错误。目标区域可能确实没有比对记录,参考序列名称可能写成chr1或1,浏览器与BAM使用的组装版本也可能不同。验证必须准备一个已知有覆盖的正对照区间和一个合理无覆盖的负对照区间,不能只看一个空白位置。
BAM主文件与索引分别保存什么
GA4GH维护的SAM/BAM规范把BAM定义为SAM比对记录的二进制表示,把BAI定义为相关但独立的索引格式。BAM保存文件头、参考信息与每条比对记录;索引并不复制所有记录,而是保存参考区间与压缩文件位置之间的定位信息。
BAM使用BGZF分块压缩。索引中的虚拟偏移把压缩块起点与块内位置组合起来,区域查询可据此跳到少量候选块。BAI再以分箱和线性索引缩小需要读取的范围。这个机制解释了索引为什么体积小,也解释了它为何必须与当前BAM字节布局相匹配。
如果BAM重新排序、过滤、补写标签或重新压缩,即使比对内容看起来相近,压缩块位置也会改变。把旧.bai留在同名目录,工具可能仍找到它,却被带到已经不对应的虚拟偏移。索引不是只和样本名称配对,而是和这一版主文件配对。
旧索引为何可能只在部分区域失效
错配索引不一定在第一次访问时立即报错。文件头与参考字典由BAM本身读取,不依赖索引;某些浏览器还会缓存上一次画面。若两个版本的BAM前部结构相近,少数早期区间甚至可能碰巧读到可解析数据,而较后区间才明显失败。
文件名也会制造假象。sample.bam旁边有sample.bam.bai,只能说明命名符合常见约定,不能证明内容来自同一次生成。复制目录、改名主文件、只同步BAM没有同步索引,或任务失败后留下半成品,都可能产生名称正确而内容错配的组合。
最可靠的处理不是继续给旧索引改名,而是保留它作为现场证据,从当前BAM重新生成一个新索引。新旧文件的修改时间、大小和哈希可以帮助确认是否真的发生变化,但哈希不同本身不解释原因;后续仍要用区域查询验证。
坐标排序是随机访问的前提
samtools index手册明确把输入描述为坐标排序的SAM、BAM或CRAM。区域索引假定记录按参考序列与位置组织,使同一区间的数据集中在可定位的压缩块附近。按读名排序的文件适合某些配对处理,却不满足这种坐标访问假定。
文件头中的排序标签可以提供线索,但不能单独替代检查。上游工具可能保留了旧头信息,或在失败过程中只改了部分记录。索引命令若报告未排序位置,应先在副本上完成坐标排序,再生成索引;不要为了让命令通过而直接修改标签。
重新排序会产生新的BAM,所以必须重新计算哈希、保存命令与工具版本,并重新建立索引。若原文件是受控研究产物,最好把排序后文件作为新派生物,不覆盖原始交付件。
BAI与CSI怎样选择
BAI是长期使用的BAM索引格式,具有固定的分箱层级与参考坐标范围。CSI把最小区间和层级变为可配置参数,能覆盖更大的参考序列,也是较新的通用方案。某些非典型组装包含很长的参考序列时,默认BAI可能不适合,应查看工具与下游浏览器是否支持CSI。
选择CSI不是修复按钮。BAM内部损坏、索引来自另一文件、记录未按坐标排序或参考字典不一致时,换一种索引格式仍会失败。格式选择解决的是寻址范围与兼容性,文件配对和数据完整性要另外验证。
同时保存.bai与.csi时,还要知道下游工具优先读取哪一个。若旧BAI残留而新CSI有效,浏览器可能仍选到旧文件。测试目录中可以只放当前准备验证的主文件与单一索引,确认结果后再按正式工具要求部署。
快速检查通过不代表中段完整
Samtools项目说明,quickcheck会检查文件头,并在BAM或CRAM中检查文件结束标记。为了速度,它不会读取文件中间的数据,因此不能发现内部损坏。一个头部和结束块都存在的文件,中间仍可能因传输、存储或截取错误而有问题。
quickcheck通过可以排除一部分明显的截断或头部错误,但不能证明索引有效,也不能证明每个目标区域都可解压。反过来,索引命令成功也不自动验证样本身份、参考版本、所有记录语义或生物学覆盖。
需要更强验证时,应在副本上执行能够遍历全部记录的读取或统计,并保留标准错误输出与退出状态。再对多个参考序列、早中晚坐标和已知覆盖区域进行随机查询。顺序全读与随机区间都通过,才同时覆盖两条不同访问路径。
参考序列与坐标名称也会造成假空白
BAM文件头列出参考序列名称与长度。浏览器若载入另一版组装,坐标相同也可能指向不同序列;若一端使用chr1、另一端使用1,工具可能无法匹配名称。线粒体、替代单倍型与补丁序列的命名差异更常见。
把BAM头中的参考字典与浏览器当前参考逐项比较:名称、长度、组装版本以及可用时的序列校验标识。索引只能定位BAM中已有的参考记录,不能替浏览器完成错误的组装映射。
目标区间还要检查坐标约定。有的接口使用一基起始闭区间,有的内部格式使用零基起始半开区间。差一个碱基通常不会让大片段完全消失,但在窄变异或边界查询中足以产生误判。记录实际提交给工具的区域字符串,而不是只保留屏幕截图。
把三种“空白”分开记录
浏览器显示空白至少有三种含义。第一种是查询正常完成,目标区间确实返回零条记录;第二种是索引无法定位,工具在读取前就失败;第三种是已经定位到候选块,但解压或解析中途报错。三者在画面上可能同样没有轨道,处理方向却完全不同。
正常零记录通常会有成功退出状态,命令行区域查询不输出记录也不显示错误。此时应先用相邻已知覆盖区作正对照,并核对过滤条件,例如最低比对质量、重复标记或只显示特定读组。正对照可读而目标区正常为空,才有资格把“无可见比对”保留为观察结果。
索引定位失败常伴随找不到索引、索引较旧、参考不存在或无法取回区域等提示。记录完整原文,不要只截取最后一行。若错误在重新生成当前文件的索引后消失,说明配对或索引结构是主要候选;仍应确认旧索引为什么残留,避免同一发布流程再次混用版本。
解压或解析错误更接近主文件中段问题。新索引可能让工具更准确地跳到损坏位置,所以“重建后才出现明确错误”不表示新索引制造了损坏。此时全文件读取、文件传输校验和与上游原件对照比继续重建索引更重要。
还有一种界面层空白:后台查询已成功,前端因缩放范围、轨道高度、筛选或缓存没有绘制。用同一区间的命令行查询与浏览器网络日志交叉检查,可以把数据访问和画面呈现分开。本文讨论的索引验证不能替代浏览器自身的渲染诊断。
远端对象存储最容易留下版本错配
BAM和索引放在对象存储、HTTP服务器或内容分发缓存时,两个文件可能分别更新。上传新BAM后沿用旧URL,边缘节点可能仍缓存旧索引;也可能索引先更新,而主文件的大对象缓存尚未失效。客户端看到的文件名完全相同,实际取得的版本却不在同一时刻。
验证远端文件时,除URL外还要保存内容长度、ETag或服务端提供的校验和、Last-Modified以及实际响应时间。不要假定查询参数一定能绕过所有缓存;最稳妥的做法是为成对产物使用不可变版本路径,完成校验后再原子地更新指向该版本的清单或别名。
范围请求也必须可用。远端随机访问依赖HTTP Range读取目标字节区间;服务器若忽略范围请求、返回压缩过的整个对象或中间层改变响应,客户端可能退回全文件下载或直接失败。检查响应是否为预期的部分内容,并确认内容编码没有破坏BAM字节偏移。
若主文件和索引来自工作流产物,可建立一份配对清单,记录BAM哈希、索引哈希、参考组装、排序命令、samtools版本与生成时间。部署时把清单与两份文件作为同一发布单位。这样出现异常时,可以先比对远端清单,而不是依赖文件名猜测。
从错误现象决定下一项检查
若文件一开始就无法识别,先查看格式、头部与传输截断。若quickcheck失败且提示缺少结束块,优先回到上游原件或重新传输;此时建立新索引只会在不完整主文件上增加另一份产物。
若quickcheck通过、索引命令报告未排序位置,应验证真实记录顺序并在副本上坐标排序。若索引建立成功但所有区域查询都失败,检查索引命名、工具实际选择的BAI或CSI、权限与参考字典。若只有特定中段失败,则对该区执行直接读取,并与全文件遍历的错误位置对照。
若命令行区域查询正常而浏览器异常,把同一文件、索引和区域字符串交给浏览器测试,同时清理受控缓存并检查它支持的索引格式。不要再改动BAM,否则会把已验证的数据层重新变成未知版本。
若不同工具得出不同结果,记录每个工具的版本和所读取的实际路径。工具可能优先选择不同索引,或对参考名称、超长序列和损坏块采用不同容错策略。差异本身是定位线索,不应通过覆盖文件让结果表面一致。
一套不覆盖原文件的验证顺序
先把BAM和现有索引设为只读副本,记录文件大小、修改时间与SHA-256。读取文件头,保存参考序列字典、排序标签和样本读组。运行quickcheck,明确它只检查头部与结束标记。若失败,先处理主文件完整性,不要急着重建索引。
主文件通过基础检查后,确认记录实际按坐标排序。把旧索引移到独立证据目录,在工作副本旁从当前BAM生成新的BAI或CSI。不要用另一台机器或旧任务输出中同名的索引补位。
随后准备区间组:文件前部一个已知覆盖区、中段一个已知覆盖区、末部一个已知覆盖区,以及至少一个合理无覆盖区。用同一工具版本分别查询,记录返回条数、错误信息与耗时。正对照应读到记录,负对照应正常返回空,而不是报无法定位或解压错误。
若新索引仍在固定区域失败,再执行全文件读取,检查该处压缩块是否损坏;同时核对参考序列与组装版本。若全读通过而浏览器失败,可继续比较浏览器支持的索引格式、索引查找命名、缓存与区间语法。
把关键区别明确写进结果:顺序读取验证文件可从头向后解析;随机访问验证指定参考区间能否由匹配索引定位,两者不能互相替代。区域查询把参考坐标经分箱与线性索引映射到BGZF压缩流的虚拟偏移,索引错配会把读取带到错误或不存在的数据块。
重建索引不能修复损坏的BAM、错误参考版本、样本错置或实际未按坐标排序的记录。保留原文件和旧索引,记录哈希与头信息,再从当前BAM生成新索引并用正负区间对照,才能知道修复的是定位层,而不是悄悄改变研究数据。
本文核对资料
- GA4GH Large Scale Genomics Work Stream:《Sequence Alignment/Map Format Specification》,2026-04-22
- Samtools项目:《samtools index manual page》,2026-07-09
- Samtools项目:《samtools quickcheck manual page》,2026-07-09
资料来源
- GA4GH Large Scale Genomics Work Stream:《Sequence Alignment/Map Format Specification》,发布或更新于 2026-04-22
- Samtools项目:《samtools index manual page》,发布或更新于 2026-07-09
- Samtools项目:《samtools quickcheck manual page》,发布或更新于 2026-07-09