k-mer使用完美散列计数到R中

时间:2016-06-26 01:07:47

标签: c++ r math bioinformatics rcpp

我在DNA K-mers计数中工作,我准备这个公式以使用完美哈希表来解决计数:link。 我使用Rcpp API(C ++)将代码集成到R:

#include <Rcpp.h>
using namespace Rcpp;
/*
this code can be used with c++ by replacing IntegerVector by std::vector<int>
*/
//************************************************
inline const short int V (const char x){
  switch(x){
  case 'A':case 'a':
    return 0;
    break;
  case 'C':case 'c':
    return 1;
    break;   
  case 'G':case 'g':
    return 2;
    break;
  default:
    return 3;
  break;  
  }

}

inline unsigned int  X0( const std::string A,const int k ,const int n){
  unsigned int  result=0;
  int j=k;
  for( int i=n-1;i>n-k-1;i--) {
    result+= pow(4,k-j)*V(A[i]);
  j--;
  }
  return result;
}

// [[Rcpp::export]]
inline IntegerVector kmer4(const std::string A,const int n,const int k)
{

  IntegerVector P(pow(4,k));                  
  int x=X0(A,k,n);                              
  P[x]++;                   
  const int N=pow(4,k-1);               
  for( int i=n-k-1;i>-1;i--){
    x=N*V(A[i])+x/4-x%4/4;
    P[x]++;
  }
  return P;
}

有两个问题:

  1. 假设kmer的索引x,则x的补码为(4 ^ k)-x-1。我们可以使用前面的公式之类的数字运算来反转吗?

  2. 运行时有两个问题:迭代字符串和矢量创建,其中k超过8。 是否有解决这些问题的想法?

1 个答案:

答案 0 :(得分:0)

第1项:我不熟悉k-mer计数,x的定义有点不稳定。如果您可以更新您的问题,那么我将尝试解决第1点。但是,对我而言,似乎您只需要使用从基数10转换回基数4的算法?

第2项:是的。正在执行的迭代不是最理想的,因为您经常从string转换为int,依此类推。而且,为什么要声明函数inline?此外,数据传递到A的数量有多大?

为了解决这个问题,我们将字符串完全移植到std::vector<int>。实际上,我会说直接将它移植到std::vector<int>并避免列出它可以切换到非rcpp代码。另外,我们选择使用pass by reference范例而不仅仅是const变量。最后,我减少了inline声明的数量。

#include <Rcpp.h>
using namespace Rcpp;

//************************************************
inline const short int V (const char x){
  switch(x){
  case 'A':case 'a':
    return 0;
    break;
  case 'C':case 'c':
    return 1;
    break;   
  case 'G':case 'g':
    return 2;
    break;
  default:
    return 3;
  break;  
  }

}

std::vector<int> conv_A2V(const std::string & A){
 unsigned int obs = A.length()
 std::vector<int> out(obs);
 for(unsigned int i = 0; i < obs; i++){
   out(i) = V(A[i]);
 }
 return out;
}

unsigned int X0( const std::vector<int> & V_A, const int k, const int n){
  unsigned int  result=0;
  int j=k;
  for( int i=n-1;i>n-k-1;i--) {
    result+= pow(4,k-j)*V_A[i];
  j--;
  }
  return result;
}

// [[Rcpp::export]]
IntegerVector kmer4(const std::string A, const int n,const int k)
{
  // Convert
  std::vector<int> V_A = conv_A2V(A);

  IntegerVector P(pow(4,k));                  
  int x=X0(V_A,k,n);                              
  P[x]++;                   
  const int N=pow(4,k-1);               
  for( int i=n-k-1;i>-1;i--){
    x=N*V_A[i]+x/4-x%4/4;
    P[x]++;
  }
  return P;
}