【问题标题】:What is a good way to implement getting a consensus sequence in Java?在 Java 中实现共识序列的好方法是什么?
【发布时间】:2012-01-25 06:59:14
【问题描述】:

我有以下问题:

  • 我有 2 串 DNA 序列(由 ACGT 组成),它们有一个或两个不同 斑点。
  • 找出差异是微不足道的,所以让我们忽略它
  • 对于每个差异,我想获得代表两种可能性的 consensus symbol(例如,M 代表 A 或 C)

我知道我可以制作一个巨大的if-cascade,但我想这不仅丑陋且难以维护,而且速度也很慢。

有什么快速、易于维护的方法来实现它?也许是某种查找表,或者组合的矩阵?任何代码示例将不胜感激。我会使用 Biojava,但我已经使用的当前版本不提供该功能(或者我还没有找到它......)。

更新:这里似乎有点混乱。共识符号是单个字符,代表两个序列中的单个字符。

String1 和 String2 是,例如“ACGT”和“ACCT”——它们在位置 2 上不匹配。所以,我希望共识字符串是 ACST,因为 S 代表“C 或 G”

我想做一个这样的方法:

char getConsensus(char a, char b)

更新 2:如果我只有 2 个序列,一些建议的方法可以工作。我可能需要对这些“共识”进行多次迭代,因此输入字母可能会从“ACGT”增加到“ACGTRYKMSWBDHVN”,这会使一些提议的方法难以编写和维护。

【问题讨论】:

  • 我会在这里查看代码示例shootout.alioth.debian.org 这有一些编码 DNA 序列的最快方法。
  • @PeterLawrey 谢谢,但改变编程语言并不是我想要的。
  • 所有的例子都是用Java写的(还有很多其他的)
  • @PeterLawrey 你能给我一个直接链接吗?我不明白您要指向我的那个页面上的确切内容。我在那里看不到我的问题的解决方案。
  • 我不清楚你到底想做什么,所以我建议了以不同方式分析不同编码的 DNA 序列的代码。我必须了解您的具体问题才能给出更具体的答案。

标签: java bioinformatics biojava


【解决方案1】:

您可以只使用 HashMap<String, String> 将冲突/差异映射到共识符号。您可以“硬编码”(填写您的应用程序的代码)或在您的应用程序启动期间从某些外部源(文件、数据库等)填写它。然后你只要有不同就使用它。

String consensusSymbol = consensusMap.get(differenceString);

编辑:为了满足您的 API 请求;]

Map<String, Character> consensusMap; // let's assume this is filled somewhere
...
char getConsensus(char a, char b) {
    return consensusMap.get("" + a + b);
}

我知道这看起来很粗糙,但我想你明白了。这可能比查找表稍慢,但也更容易维护。

另一个编辑:

如果你真的想要超快的东西并且你实际上使用char 类型,你可以创建一个二维表并用字符索引它(因为它们被解释为数字)。

char lookup[][] = new char[256][256]; // all "english" letters will be below 256
//... fill it... e. g. lookup['A']['C'] = 'M';
char consensus = lookup['A']['C'];

【讨论】:

  • 啊,是的,我似乎不清楚这个问题。我试图在问题中更新它。不幸的是,哈希不是解决问题的正确方法,我需要矩阵查找之类的东西。
  • 感谢您的编辑。如果我只有 ACGT 作为输入的可能性,那可以工作。但是,使用 ACGTRYKMSWBDHVN 作为输入的所有可能性填充该共识映射将产生 225 个条目。仍然很快,但要维护一个 PITA。有什么可以改进的吗?
  • 好的,查找矩阵将是迄今为止最好的解决方案。谢谢。
  • 如果您将(差异,一致)行放在一个 sql 数据库中并从那里读取它们(您只需执行一次,因此不会出现性能问题),您可以轻松维护。跨度>
  • 我现在使用枚举来实现它,因为它比您建议的查找数组更具可读性和紧凑性,但无论哪种方式都可以。完成打字后,我会提出解决方案,因为工作量很大。
【解决方案2】:

一个简单、快速的解决方案是使用按位或。

在启动时,初始化两个表:

  • 一个包含 128 个元素的稀疏表,用于将核苷酸映射到单个位。 “稀疏”意味着您只需设置您将使用的成员:IUPAC 代码的大小写。
  • 一个 16 元素表,用于将按位一致性映射到 IUPAC 核苷酸代码。

要获得单一立场的共识:

  1. 使用第一个表中的核苷酸作为索引,以获得按位表示。
  2. 按位或按位表示。
  3. 使用按位或作为 16 元素表的索引。

这里有一个简单的按位表示可以帮助您入门:

    private static final int A = 1 << 3;
    private static final int C = 1 << 2;
    private static final int G = 1 << 1;
    private static final int T = 1 << 0; 

这样设置第一个表的成员:

    characterToBitwiseTable[ 'd' ] = A | G | T;
    characterToBitwiseTable[ 'D' ] = A | G | T;

这样设置第二个表的成员:

    bitwiseToCharacterTable[ A | G | T ] = 'd';

【讨论】:

    【解决方案3】:

    鉴于它们都是独特的符号,我会选择Enum

    public Enum ConsensusSymbol
    {
        A("A"), // simple case
        // ....
        GTUC("B"),
        // etc
        // last entry:
        AGCTU("N");
    
        // Not sure what X means?
    
        private final String symbol;
    
        ConsensusSymbol(final String symbol)
        {
            this.symbol = symbol;
        }
    
        public String getSymbol()
        {
            return symbol;
        }
    }
    

    然后,当你遇到不同时,使用.valueOf()

    final ConsensusSymbol symbol;
    
    try {
        symbol = ConsensusSymbol.valueOf("THESEQUENCE");
    } catch (IllegalArgumentException e) { // Unknown sequence
        // TODO
    }
    

    例如,如果您遇到 GTUC 作为字符串,Enum.valueOf("GTUC") 将返回 GTUC 枚举值,并且在该值上调用 getSymbol() 将返回 "B"

    【讨论】:

    • 谢谢,但共识符号不能这样工作。 “G”或“T”或“U”或“C”映射到“B”,而不是字符串“GTUC”。
    • 啊,好吧...但是如果遇到A,你如何确定选择哪个符号呢?我想我遗漏了一些明显的东西。
    • 我有 2 个序列。因此,在“我”的位置,我有 2 个要“一致”的字符
    • 好的,还有一些我没有得到的东西,因为其中一些代码包含两个以上的字符......这些只是被忽略了吗?对不起,如果我听起来很厚。
    • 别担心,我知道被这些生物信息学的东西弄糊涂了。例如,String1 和 String2 是“ACGT”和“ACCT”——它们在位置 2(或 3,如果你算作遗传学研究人员,但我们不要去那里)不匹配所以,我想要一个共识字符串是 ACST,因为S 代表“C 或 G”——我正在寻找一种方法来实现函数 'char getConsensus(char a, char b)'
    【解决方案4】:

    可能的组合约为 20。因此不存在真正的性能问题。 如果你不想做一个大的 if else 块,最快的解决方案是构建一个 Tree 数据结构。 http://en.wikipedia.org/wiki/Tree_data_structure。这是完成您想做的事情的最快方式。

    在一棵树中,你放置所有可能的组合,然后输入字符串,它会遍历树来找到一个符号的最长匹配序列

    你想要一个有插图的例子吗?

    PS:所有的人工智能软件都使用了最快、最适应的Tree方法。

    【讨论】:

    • 哈希映射比树快(尽管在这种情况下差异不大)。
    • 如果我只有 ACGT 和 ACGT,我有 16 种组合。但是,如果我也允许歧义符号本身,我会得到一个 15x15 的可能性矩阵。我不明白树会如何帮助我...
    • @pablochan HashMap 不适合他想做的事!
    • @Adel Boutros:怎么会这样?除非我对这个问题有很大的误解,否则这很容易通过哈希映射来解决。
    • 啊,是的,我似乎不清楚这个问题。我试图在问题中更新它。一棵树对于您如何看待问题是最佳的,真的。但问题不是“将一系列字符与单个字符匹配”,而是“从 2 个字符串中选择 2 个字符 [已经知道] 并找到一个字符来表示这两个字符
    【解决方案5】:

    考虑一次读取多个序列 - 我会:

    1. 将序列中同一位置的所有字符放入一个集合中
    2. 对集合中的值进行排序和连接,并像 fge 的示例一样使用 enum.valueOf()
    3. 将获取的值用作 EnumMap 的键,并将 consesus 符号作为值

    可能有一些方法可以优化第二步和第一步。

    【讨论】:

      【解决方案6】:

      一个可能的使用枚举的解决方案,灵感来自 pablochan,来自biostar.stackexchange.com 的一些输入:

      enum lut {
           AA('A'), AC('M'), AG('R'), AT('W'), AR('R'), AY('H'), AK('D'), AM('M'), AS('V'), AW('W'), AB('N'), AD('D'), AH('H'), AV('V'), AN('N'),
           CA('M'), CC('C'), CG('S'), CT('Y'), CR('V'), CY('Y'), CK('B'), CM('M'), CS('S'), CW('H'), CB('B'), CD('N'), CH('H'), CV('V'), CN('N'),
           GA('R'), GC('S'), GG('G'), GT('K'), GR('R'), GY('B'), GK('K'), GM('V'), GS('S'), GW('D'), GB('B'), GD('D'), GH('N'), GV('V'), GN('N'),
           TA('W'), TC('Y'), TG('K'), TT('T'), TR('D'), TY('Y'), TK('K'), TM('H'), TS('B'), TW('W'), TB('B'), TD('D'), TH('H'), TV('N'), TN('N'),
           RA('R'), RC('V'), RG('R'), RT('D'), RR('R'), RY('N'), RK('D'), RM('V'), RS('V'), RW('D'), RB('N'), RD('D'), RH('N'), RV('V'), RN('N'),
           YA('H'), YC('Y'), YG('B'), YT('Y'), YR('N'), YY('Y'), YK('B'), YM('H'), YS('B'), YW('H'), YB('B'), YD('N'), YH('H'), YV('N'), YN('N'),
           KA('D'), KC('B'), KG('K'), KT('K'), KR('D'), KY('B'), KK('K'), KM('N'), KS('B'), KW('D'), KB('B'), KD('D'), KH('N'), KV('N'), KN('N'),
           MA('M'), MC('M'), MG('V'), MT('H'), MR('V'), MY('H'), MK('N'), MM('M'), MS('V'), MW('H'), MB('N'), MD('N'), MH('H'), MV('V'), MN('N'),
           SA('V'), SC('S'), SG('S'), ST('B'), SR('V'), SY('B'), SK('B'), SM('V'), SS('S'), SW('N'), SB('B'), SD('N'), SH('N'), SV('V'), SN('N'),
           WA('W'), WC('H'), WG('D'), WT('W'), WR('D'), WY('H'), WK('D'), WM('H'), WS('N'), WW('W'), WB('N'), WD('D'), WH('H'), WV('N'), WN('N'), 
           BA('N'), BC('B'), BG('B'), BT('B'), BR('N'), BY('B'), BK('B'), BM('N'), BS('B'), BW('N'), BB('B'), BD('N'), BH('N'), BV('N'), BN('N'),
           DA('D'), DC('N'), DG('D'), DT('D'), DR('D'), DY('N'), DK('D'), DM('N'), DS('N'), DW('D'), DB('N'), DD('D'), DH('N'), DV('N'), DN('N'),
           HA('H'), HC('H'), HG('N'), HT('H'), HR('N'), HY('H'), HK('N'), HM('H'), HS('N'), HW('H'), HB('N'), HD('N'), HH('H'), HV('N'), HN('N'),
           VA('V'), VC('V'), VG('V'), VT('N'), VR('V'), VY('N'), VK('N'), VM('V'), VS('V'), VW('N'), VB('N'), VD('N'), VH('N'), VV('V'), VN('N'),
           NA('N'), NC('N'), NG('N'), NT('N'), NR('N'), NY('N'), NK('N'), NM('N'), NS('N'), NW('N'), NB('N'), ND('N'), NH('N'), NV('N'), NN('N');
      
           char consensusChar = 'X';
      
           lut(char c) {
               consensusChar = c;
           }
      
           char getConsensusChar() {
               return consensusChar;
           }
      }
      
      char getConsensus(char a, char b) {
          return lut.valueOf("" + a + b).getConsensusChar();
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-10-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多