IO 方法

概述

常规的文件 IO 流(或方法)以 File 类描述文件的基本信息,使用单个字节作为数据写入和读取的最小单位。GBC 以 GTBManager 类描述 GTB 文件的基本信息,使用单个位点 Variant 作为数据写入和读取的最小单位。以下是最常用的 API 列表:

以下是简单的进行 GTB 文件 IO 的示例,它读取 https://pmglab.top/gbc/download/assoc.hg19.gtb 上的变异位点,筛选出坐标范围在 chr1:0-200000 的变异位点,并进行 LiftOver:

// 创建文件对象
GTBManager manager = GTBManager.load("https://pmglab.top/gbc/download/assoc.hg19.gtb");

// 创建 GTB 文件写入器
GTBWriter writer = GTBWriter.Builder.of(new File("./assoc.hg19.gtb"))
        .addField("hg38_CHROM", FieldType.Int)
        .addField("hg38_POS", FieldType.Int)
        .addSubjects(manager.getSubjects())
        .build()
        .writeMeta(manager.getMeta());

// 创建 GTB 读取器
GTBReader reader = new GTBReader(manager);

// 创建过滤器
GTBFilter filter = new GTBFilter().filterByCoordinateRange(Chromosome.get("chr1"), new Interval<>(0, 200000));

// 创建 LiftOver
LiftOver liftOver = LiftOver.load(RefGenomeVersion.hg19, RefGenomeVersion.hg38);

Variant variant;

// 按照过滤器读取位点, 只有满足条件的位点会被读入
while ((variant = reader.read(filter)) != null) {
    // liftover 并写入新坐标
    Entry<Chromosome, Integer> hg38Coordinates = liftOver.convertCoordinate(variant.getChromosome(), variant.getPosition());

    // 写入位点的新属性值
    variant.setProperty("hg38_CHROM", hg38Coordinates.getKey().getChromosomeIndex());
    variant.setProperty("hg38_POS", hg38Coordinates.getValue());

    // 写入位点
    writer.write(variant);
}
reader.close();
writer.close();

GTB 基本格式声明

GTB 的基本格式 GTBFormat 包括压缩级别、每个块最多包含的位点数量、基因型向型 3 个参数。

  • 压缩级别越高,压缩比越高,但压缩速度越慢;
  • 每个块包含的位点数越多,压缩比越高,但会影响访问性能和读写时的内存开销

为保证并行操作大规模基因型数据的可行性,GTB 文件的每个基因型块都不超过 128 MB 大小。

此外,GTBFormat 提供了以下两个常用方法,用于标准化补充列名和受试者名称:

  • checkSubjectName(String subjectName):检查受试者名称。不可见字符(如空格、制表符、换行符等)、反斜杠、等号、冒号、分号、逗号、单引号和双引号都被替换为下划线 _。
  • fieldNameChecker(String fieldName):检查字段名称是否合法。字段名称不允许为 CHROM, POS, ALLELE, GENOTYPE。

GTB 元信息

GTB 使用 GTBMeta 管理元信息。主要包含 add(String metaKey, String metaValue) 和 add(ByteCode metaKey, ByteCode metaValue) 方法。作为强制性的规定,GTBMeta 拒绝写入以 $gtbformat. 开头的元信息。

以下是使用 GTBMeta 写入和读取元信息的实例:

GTBMeta meta = new GTBMeta();

// 写入元信息
meta.add("fileformat", "VCFv4.4");
meta.add("contig", "<ID=1,assembly=b37,length=249250621>");
meta.add("contig", "<ID=2,assembly=b37,length=243199373>");
meta.add("FORMAT", "<ID=GT,Number=1,Type=String,Description=\"Genotype\">");

// 读取元信息, 返回结果为所有的键为 contig 的元信息值数组
BaseArray<ByteCode> contigs = meta.get("contig").values();

GTB 写入器

GTB 写入器 GTBWriter 和 GTBPartWriter 使用建造者模式进行初始化,GTBWriter.Builder 是它们的初始化方法。在初始化阶段,使用以下方法配置信息:

  • setFormat(GTBFormat format):设置 GTB 文件格式
  • addSubject(String subjectName):添加受试者
  • addSubjects(String[] subjectNames):添加多个受试者
  • addSubjects(Iterable<String> subjectNames):添加多个受试者
  • addField(String fieldName, FieldType fieldType):添加其他字段
  • addFields(Map<String, FieldType> fields):添加其他字段

有关 FieldType 支持的类型,请参阅:枚举 FieldType。GTBWriter 中添加了其他字段时,需要向 Variant 对象添加相应字段的属性值,否则会引发空指针异常。

完成配置后,使用 .build() 方法实例化 GTB 写入器 GTBWriter,或使用 .build(int nThreads) 实例化 GTB 分部写入器 GTBPartWriter。分部写入器将文件分为指定数量的子部份,每一个部份都独立使用 GTBWriter 进行数据写入,全部写入任务完成后根据分部索引拼接子文件:

-----  ++++++  ~~~~~~     --->      -----++++++~~~~~~   
Part1  Part2   Part3                合并

分部写入器最常用的场景是为每一个染色体分配一个子部份,完成压缩后按照染色体编号进行拼接。

GTBWriter 和 GTBPartWriter 都通过 writeMeta(String metaKey, String metaValue) 、 writeMeta(ByteCode metaKey, ByteCode metaValue) 或 writeMeta(GTBMeta metas) 写入元信息。GTBWriter 通过调用 write(Variant variant) 和 write(Variants variants) 写入变异位点。GTBPartWriter 则需要先指定分部索引,获得相应的 GTBWriter 后执行写入变异位点。完成写入后,请务必调用 close() 方法关闭文件 IO 流。

GTB 管理器

GTB 管理器对象 GTBManager 用于维护同个文件路径指向的 GTB 文件信息。它通过缓存结构设计,使得多次请求同个文件的管理器时仅扫描一次文件的索引信息,后续所有的请求都返回同一个管理器对象。加载一个 GTB 文件的管理器,请使用 GTBManager.load(Object fileObject)。

GTBManager 包含如下常用的方法:

  • getFieldNum():获取当前数据表包含的列数(添加的字段数)
  • getVariantNum():获取位点数
  • getSubjectNum():获取样本数
  • containField(String fieldName):是否包含指定的列字段
  • containSubject(String subject):是否包含指定的样本名
  • getFields():获取补充的其他字段及其类型
  • getSubjects():获取样本序列
  • getFieldType(String fieldName):获取指定字段的类型
  • indexOfSubject(String subject):获取指定样本的索引
  • subjectOfIndex(int index):获取指定索引对应的样本名
  • getMeta():获取元信息管理器
  • isOrdered():检查文件是否坐标有序

GTB 过滤器

GTB 过滤器 GTBFilter 对象用于读取 GTB 变异位点时快速进行过滤。它包含以下常用方法,这些方法建立了变异位点对象 Variant 和基因型序列 Genotypes 的筛选条件:

  • filterByAC(Interval<Integer> range):按照等位基因频数过滤
  • filterByAN(Interval<Integer> range):按照等位基因总数过滤
  • filterByAF(Interval<Float> range):按照等位基因频率过滤
  • filterByAlleleNum(Interval<Float> range):按照可变等位基因数过滤位点
  • filterByChromosome(Chromosome chromosome):按照染色体进行过滤(只读取指定的染色体)
  • filterByChromosomes(Chromosome... chromosomes):按照多个染色体进行过滤(只读取指定的染色体)
  • filterByChromosomes(Iterable<Chromosome> chromosomes):按照多个染色体进行过滤(只读取指定的染色体)
  • filterByCoordinate(Chromosome chromosome, int position):添加染色体-坐标过滤器(只读取指定的坐标)
  • filterByCoordinates(Chromosome chromosome, Iterable<Integer>poses):添加染色体-坐标过滤器(只读取指定的坐标)。当指定的染色体的筛选坐标为 null 时,表示读取该染色体的所有位点
  • filterByCoordinates(Map<Chromosome, Iterable<Integer>> poses):添加多个染色体-坐标过滤器(只读取指定的坐标)
  • filterByCoordinateRange(Chromosome chromosome, Interval<Integer> ranges):添加染色体-坐标范围过滤器(只读取指定的坐标)
  • filterByCoordinateRanges(Map<Chromosome, Interval<Integer>> poses):添加多个染色体-坐标范围过滤器(只读取指定的坐标)。当指定的染色体的筛选坐标范围为 null 时,表示读取该染色体的所有位点
  • filterByVariantIndex(Interval<Long> indexRangeOfVariant):添加变异位点指针范围过滤器

此外,对于复杂的条件判断,可以使用以下方法进行:

  • filterByVariant(Function<Variant, Boolean> function):位点过滤器

GTBFilter 支持通过链式调用的方式添加过滤器,如下所示添加多个复杂过滤器方法:

LiftOver liftOver = LiftOver.load(RefGenomeVersion.hg19, RefGenomeVersion.hg38);
GTBFilter filter = new GTBFilter()
        .filterByAC(new Interval<>(0, 100))
        .filterByAF(new Interval<>(0.1f, 0.9f))
        .filterByChromosome(Chromosome.get("chr1"))
        .filterByVariant(variant -> liftOver.convertCoordinate(variant) != null);

GTB 读取器

GTB 读取器 GTBReader 用于创建一个按行读取变异位点的读取器实例,包含以下构造器方法:

  • GTBReader(Object manager):默认构造器方法,加载所有的基因和补充字段
  • GTBReader(Object manager, boolean loadGenotype):构造器方法,可选是否加载基因型
  • GTBReader(Object manager, boolean loadGenotype, boolean loadField):构造器方法,可选是否加载基因型、补充字段
  • GTBReader(Object manager, boolean loadGenotype, Iterable<String> fields):构造器方法,可选是否加载基因型,以及筛选加载的补充字段。fields 为 null 时表示加载所有的补充字段

请注意,单个 GTBReader 是线程不安全的,如果需要并行读取文件,请创建多个 GTBReader 实例。

实例化的 GTBReader 主要包含以下方法:

  • read():读取并返回一个变异位点对象,到达文件尾部时返回 null
  • reads():读取连续地、坐标相同的多个变异位点,并返回一个多位点对象,当 GTB 文件无序时,它无法返回正确的结果
  • read(GTBFilter filter):读取一个满足过滤条件的位点,当不存在这样的位点时返回 null,并且文件指针移动到末尾
  • tell():获取文件的位点指针(即位点索引)
  • seek(long variantIndex):移动文件位点指针到指定位置
  • seek(GTBFilter filter):移动文件位点指针到满足过滤器条件的位置,当不存在这样的位点时返回 false,文件指针保持不变
  • limit(Interval<Long> ranges):设置当前读取器的读取范围
  • remaining():获取当前读取器剩余可读的记录条目数
  • part(int nParts):将 GTBReader 从当前指针位置到文件末尾均等地分为 nPart 份

对于读取的位点,通过 Variant.getProperty(IGenotypes.class) 获得基因型序列。有关基因型序列的操作方法详见 IGenotypes。

Copyright ©张柳彬 all right reserved文档修订时间: 2023-04-18 20:16:55

results matching ""

    No results matching ""