GATK AlleleList接口介绍

在 GATK(Genome Analysis Toolkit)中,AlleleList 接口是一个用来表示等位基因(alleles)列表的接口。Allele 是遗传学中用于表示某一特定基因座的不同形式的一个基本单位。AlleleList 接口定义了一些操作,使得处理和访问一组等位基因更加方便。

AlleleList 的实现类和继承接口

使用场景

AlleleList 及其实现类在 GATK 中主要用于表示和操作基因型数据中的等位基因集合。典型场景包括:

  • 变异检测 :在不同样本中检测和分析不同的等位基因时,需要管理多个等位基因的集合,这时候会用到 AlleleList
  • 基因型计算:在计算样本的基因型时,可能需要迭代多个等位基因,并根据等位基因的组合进行计算。

通过 AlleleList 接口,GATK 提供了一个统一的方式来处理等位基因列表,增强了代码的可读性和模块化,使得等位基因的管理变得更加直观和高效。

AlleleList接口源码

复制代码
package org.broadinstitute.hellbender.utils.genotyper;

import htsjdk.variant.variantcontext.Allele;
import org.broadinstitute.hellbender.utils.Utils;

import java.util.AbstractList;
import java.util.List;

/**
 * Minimal interface for random access to a collection of Alleles.
 */
//Note: Names in this interface are unusual because of name clash in a subclass.
// For example the name of AlleleList.alleleCount() cannot be simply size(), as would be usual,
// because {@link ReadLikelihoods} implements AlleleList and SampleList and then size() would be ambiguous.
public interface AlleleList<A extends Allele> {

    static <A extends Allele> AlleleList<A> newList(final List<A> alleles) {
        return new IndexedAlleleList<A>(alleles);
    }

    /**
     * Returns the number of alleles in this AlleleList.
     */
    int numberOfAlleles();

    /**
     * Returns the index of the given Allele in this AlleleList.
     * Returns a negative number if the given allele is not present in this AlleleList.
     * @throws IllegalArgumentException if allele is null.
     */
    int indexOfAllele(final Allele allele);

    /**
     * Returns the allele at the given index in this AlleleList.
     * @throws IllegalArgumentException if index is negative or equal
     * to or higher than the number of elements in this AlleleList {@link AlleleList#numberOfAlleles()}).
     */
    A getAllele(final int index);

    /**
     * Returns <code>true</code> if this AlleleList contains the specified allele
     * and <code>false</code> otherwise.
     */
    default boolean containsAllele(final Allele allele) {
        return indexOfAllele(allele) >= 0;
    }

    AlleleList<Allele> EMPTY_LIST = new AlleleList<Allele>() {
        @Override
        public int numberOfAlleles() {
            return 0;
        }

        @Override
        public int indexOfAllele(final Allele allele) {
            Utils.nonNull(allele);
            return -1;
        }

        @Override
        public Allele getAllele(final int index) {
            throw new IllegalArgumentException("allele index is out of range");  //we know this without checking because it's an empty list
        }
    };

    /**
     * Returns an unmodifiable empty allele-list.
     * @param <A> the allele class.
     * @return never {@code null}.
     */
    @SuppressWarnings("unchecked")
    static <A extends Allele> AlleleList<A> emptyAlleleList() {
        return (AlleleList<A>) EMPTY_LIST;
    }

    /**
     * Checks whether two allele lists are in fact the same.
     * @param first one list to compare.
     * @param second another list to compare.
     *
     * @throws IllegalArgumentException if if either list is {@code null}.
     *
     * @return {@code true} iff both list are equal.
     */
    static <A extends Allele> boolean equals(final AlleleList<A> first, final AlleleList<A> second) {
        if (first == null || second == null) {
            throw new IllegalArgumentException("no null list allowed");
        }
        final int alleleCount = first.numberOfAlleles();
        if (alleleCount != second.numberOfAlleles()) {
            return false;
        }

        for (int i = 0; i < alleleCount; i++) {
            final A firstSample = first.getAllele(i);
            Utils.nonNull(firstSample, "no null samples allowed in sample-lists: first list at " + i);
            final A secondSample = second.getAllele(i);
            Utils.nonNull(secondSample,"no null samples allowed in sample-list: second list at " + i);
            if (!firstSample.equals(secondSample)) {
                return false;
            }
        }

        return true;
    }

    /**
     * Resolves the index of the reference allele in an allele-list.
     *
     * <p>
     *     If there is no reference allele, it returns -1. If there is more than one reference allele,
     *     it returns the first occurrence (lowest index).
     * </p>
     *
     *
     * @throws IllegalArgumentException if {@code list} is {@code null}.
     *
     * @return -1 if there is no reference allele, or a values in [0,{@code list.alleleCount()}).
     */
    default int indexOfReference() {
        final int alleleCount = this.numberOfAlleles();
        for (int i = 0; i < alleleCount; i++) {
            if (this.getAllele(i).isReference()) {
                return i;
            }
        }
        return -1;
    }

    /**
     * Returns a {@link List} unmodifiable view of this allele-list
     *
     * @return never {@code null}.
     */
    default List<A> asListOfAlleles() {
        return new AbstractList<A>() {

            @Override
            public A get(final int index) {
                return AlleleList.this.getAllele(index);
            }

            @Override
            public int size() {
                return AlleleList.this.numberOfAlleles();
            }
        };
    }

    /**
     * Returns a permutation between two allele lists.
     * @param target the target allele list.
     *
     * @throws IllegalArgumentException if {@code target} is {@code null}, or
     * elements in {@code target} is not contained in {@code this}
     *
     * @return never {@code null}
     */
    default AlleleListPermutation<A> permutation(final AlleleList<A> target) {
        if (equals(this, target)) {
            return new NonPermutation<>(this);
        } else {
            return new ActualPermutation<>(this, target);
        }
    }

    /**
     * This is the identity permutation.
     */
    final class NonPermutation<A extends Allele> implements AlleleListPermutation<A> {

        private final AlleleList<A> list;

        NonPermutation(final AlleleList<A> original) {
            list = original;
        }

        @Override
        public boolean isPartial() {
            return false;
        }

        @Override
        public boolean isNonPermuted() {
            return true;
        }

        @Override
        public int toIndex(final int fromIndex) {
            return fromIndex;
        }

        @Override
        public int fromIndex(final int toIndex) {
            return toIndex;
        }

        @Override
        public boolean isKept(final int fromIndex) { return true; }

        @Override
        public int fromSize() {
            return list.numberOfAlleles();
        }

        @Override
        public int toSize() {
            return list.numberOfAlleles();
        }

        @Override
        public List<A> fromList() {
            return list.asListOfAlleles();
        }

        @Override
        public List<A> toList() {
            return list.asListOfAlleles();
        }

        @Override
        public int numberOfAlleles() {
            return list.numberOfAlleles();
        }

        @Override
        public int indexOfAllele(final Allele allele) {
            return list.indexOfAllele(allele);
        }

        @Override
        public A getAllele(final int index) {
            return list.getAllele(index);
        }
    }

    final class ActualPermutation<A extends Allele> implements AlleleListPermutation<A> {

        private final AlleleList<A> from;

        private final AlleleList<A> to;

        private final int[] fromIndex;

        private final boolean[] keptFromIndices;
        
        private final boolean nonPermuted;

        private final boolean isPartial;

        private ActualPermutation(final AlleleList<A> original, final AlleleList<A> target) {
            this.from = original;
            this.to = target;
            keptFromIndices = new boolean[original.numberOfAlleles()];
            final int toSize = target.numberOfAlleles();
            final int fromSize = original.numberOfAlleles();
            if (fromSize < toSize) {
                throw new IllegalArgumentException("target allele list is not a permutation of the original allele list");
            }

            fromIndex = new int[toSize];
            boolean nonPermuted = fromSize == toSize;
            this.isPartial = !nonPermuted;
            for (int i = 0; i < toSize; i++) {
                final int originalIndex = original.indexOfAllele(target.getAllele(i));
                if (originalIndex < 0) {
                    throw new IllegalArgumentException("target allele list is not a permutation of the original allele list");
                }
                keptFromIndices[originalIndex] = true;
                fromIndex[i] = originalIndex;
                nonPermuted &= originalIndex == i;
            }

            this.nonPermuted = nonPermuted;
        }

        @Override
        public boolean isPartial() {
            return isPartial;
        }

        @Override
        public boolean isNonPermuted() {
            return nonPermuted;
        }

        @Override
        public int toIndex(final int fromIndex) {
            return to.indexOfAllele(from.getAllele(fromIndex));
        }

        @Override
        public int fromIndex(final int toIndex) {
            return fromIndex[toIndex];
        }

        @Override
        public boolean isKept(final int fromIndex) {
            return keptFromIndices[fromIndex];
        }

        @Override
        public int fromSize() {
            return from.numberOfAlleles();
        }

        @Override
        public int toSize() {
            return to.numberOfAlleles();
        }

        @Override
        public List<A> fromList() {
            return from.asListOfAlleles();
        }

        @Override
        public List<A> toList() {
            return to.asListOfAlleles();
        }

        @Override
        public int numberOfAlleles() {
            return to.numberOfAlleles();
        }

        @Override
        public int indexOfAllele(final Allele allele) {
            return to.indexOfAllele(allele);
        }

        @Override
        public A getAllele(final int index) {
            return to.getAllele(index);
        }
    }
}
相关推荐
岁忧4 分钟前
(LeetCode 每日一题) 1865. 找出和为指定值的下标对 (哈希表)
java·c++·算法·leetcode·go·散列表
YuTaoShao8 分钟前
【LeetCode 热题 100】240. 搜索二维矩阵 II——排除法
java·算法·leetcode
考虑考虑1 小时前
JDK9中的dropWhile
java·后端·java ee
想躺平的咸鱼干1 小时前
Volatile解决指令重排和单例模式
java·开发语言·单例模式·线程·并发编程
hqxstudying2 小时前
java依赖注入方法
java·spring·log4j·ioc·依赖
·云扬·2 小时前
【Java源码阅读系列37】深度解读Java BufferedReader 源码
java·开发语言
Bug退退退1233 小时前
RabbitMQ 高级特性之重试机制
java·分布式·spring·rabbitmq
小皮侠3 小时前
nginx的使用
java·运维·服务器·前端·git·nginx·github
Zz_waiting.3 小时前
Javaweb - 10.4 ServletConfig 和 ServletContext
java·开发语言·前端·servlet·servletconfig·servletcontext·域对象
全栈凯哥3 小时前
02.SpringBoot常用Utils工具类详解
java·spring boot·后端