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);
        }
    }
}

  • 6
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值