mapq.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335
  1. /*
  2. * nvbio
  3. * Copyright (c) 2011-2014, NVIDIA CORPORATION. All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions are met:
  7. * * Redistributions of source code must retain the above copyright
  8. * notice, this list of conditions and the following disclaimer.
  9. * * Redistributions in binary form must reproduce the above copyright
  10. * notice, this list of conditions and the following disclaimer in the
  11. * documentation and/or other materials provided with the distribution.
  12. * * Neither the name of the NVIDIA CORPORATION nor the
  13. * names of its contributors may be used to endorse or promote products
  14. * derived from this software without specific prior written permission.
  15. *
  16. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  17. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  18. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  19. * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY
  20. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  21. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  22. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  23. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  24. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  25. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  26. */
  27. #pragma once
  28. #include <nvBowtie/bowtie2/cuda/defs.h>
  29. #include <nvBowtie/bowtie2/cuda/stats.h>
  30. #include <nvbio/io/alignments.h>
  31. #include <nvbio/io/output/output_types.h>
  32. namespace nvbio {
  33. namespace bowtie2 {
  34. namespace cuda {
  35. /// Bowtie2 Mapping Quality Calculator, V3
  36. ///
  37. template <typename ScoringSchemeType>
  38. struct BowtieMapq3
  39. {
  40. typedef ScoringSchemeType scoring_scheme_type;
  41. /// constructor
  42. ///
  43. BowtieMapq3(const ScoringSchemeType sc) : m_sc(sc) {}
  44. /// compute mapping quality
  45. ///
  46. NVBIO_HOST_DEVICE
  47. uint32 operator() (
  48. const io::BestPairedAlignments& best_alignments,
  49. const uint32 read_len,
  50. const uint32 o_read_len) const
  51. {
  52. // no second best alignment, perfect score
  53. const int unpaired_one_perfect = 44;
  54. // no second best alignment
  55. const int unpaired_one[11] =
  56. {
  57. 43, 42, 41, 36, 32, 27, 20, 11, 4, 1, 0
  58. };
  59. // two alignment scores, the best of which has perfect score
  60. const int unpaired_two_perfect[11] =
  61. {
  62. 2, 16, 23, 30, 31, 32, 34, 36, 38, 40, 42
  63. };
  64. // two alignment scores, the best of which has a non perfect score
  65. const int unpaired_two[11][11] =
  66. {
  67. { 2, 2, 2, 1, 1, 0, 0, 0, 0, 0, 0 },
  68. { 20, 14, 7, 3, 2, 1, 0, 0, 0, 0, 0 },
  69. { 20, 16, 10, 6, 3, 1, 0, 0, 0, 0, 0 },
  70. { 20, 17, 13, 9, 3, 1, 1, 0, 0, 0, 0 },
  71. { 21, 19, 15, 9, 5, 2, 2, 0, 0, 0, 0 },
  72. { 22, 21, 16, 11, 10, 5, 0, 0, 0, 0, 0 },
  73. { 23, 22, 19, 16, 11, 0, 0, 0, 0, 0, 0 },
  74. { 24, 25, 21, 30, 0, 0, 0, 0, 0, 0, 0 },
  75. { 30, 26, 29, 0, 0, 0, 0, 0, 0, 0, 0 },
  76. { 30, 27, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
  77. { 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
  78. };
  79. // paired alignment, one perfect score
  80. const int paired_one_perfect = 44;
  81. //
  82. // TODO: if paired, return paired_one_perfect
  83. //
  84. if (best_alignments.is_paired())
  85. return paired_one_perfect;
  86. const float max_score = (float)m_sc.perfect_score( read_len );
  87. const float min_score = (float)m_sc.min_score( read_len );
  88. const float norm_factor = 10.0f / (max_score - min_score);
  89. // check whether the best score is beyond the minimum threshold
  90. if (best_alignments.best_score() < min_score)
  91. return 0;
  92. const int best = std::max( (int)max_score - best_alignments.best_score(), 0 ); // negated best score
  93. const int best_bin = (int)(float(best) * norm_factor + 0.5f);
  94. const bool has_second = best_alignments.has_second();
  95. // if (info)
  96. // {
  97. // info->best = best;
  98. // info->second_best = has_second ? best_alignments.second_score() : 255;
  99. // }
  100. // check whether there are two alignment scores or just one
  101. if (has_second)
  102. {
  103. const int diff = best_alignments.best_score() - best_alignments.second_score();
  104. const int diff_bin = (int)(float(diff) * norm_factor + 0.5f);
  105. if (best == max_score)
  106. return unpaired_two_perfect[best_bin];
  107. else
  108. return unpaired_two[diff_bin][best_bin];
  109. }
  110. else
  111. {
  112. if (best == max_score)
  113. return unpaired_one_perfect;
  114. else
  115. return unpaired_one[best_bin];
  116. }
  117. }
  118. private:
  119. ScoringSchemeType m_sc;
  120. };
  121. /// Bowtie2 Mapping Quality Calculator, V2
  122. ///
  123. template <typename ScoringSchemeType>
  124. struct BowtieMapq2
  125. {
  126. typedef ScoringSchemeType scoring_scheme_type;
  127. /// constructor
  128. ///
  129. BowtieMapq2(const ScoringSchemeType sc) : m_sc(sc) {}
  130. /// compute mapping quality
  131. ///
  132. NVBIO_HOST_DEVICE
  133. uint32 operator() (
  134. const io::BestPairedAlignments& best_alignments,
  135. const uint32 read_len,
  136. const uint32 o_read_len) const
  137. {
  138. bool has_second = best_alignments.has_second();
  139. const float max_score = (float)m_sc.perfect_score( read_len ) +
  140. (best_alignments.is_paired() ? m_sc.perfect_score( o_read_len ) : 0);
  141. const float min_score = (float)m_sc.min_score( read_len ) +
  142. (best_alignments.is_paired() ? m_sc.min_score( o_read_len ) : 0);
  143. const float diff = (max_score - min_score); // range of scores
  144. const float best = (float)best_alignments.best_score();
  145. float second_best = min_score-1;
  146. if (best < min_score)
  147. return 0;
  148. // best score but normalized so that 0 = worst valid score
  149. const float best_over = best - min_score;
  150. // if (info)
  151. // {
  152. // info->best = (int32)best;
  153. // info->second_best = (int32)second_best;
  154. // }
  155. if (m_sc.m_monotone)
  156. {
  157. // global alignment
  158. if (!has_second)
  159. {
  160. if (best_over >= diff * 0.8f) return 42;
  161. else if (best_over >= diff * 0.7f) return 40;
  162. else if (best_over >= diff * 0.6f) return 24;
  163. else if (best_over >= diff * 0.5f) return 23;
  164. else if (best_over >= diff * 0.4f) return 8;
  165. else if (best_over >= diff * 0.3f) return 3;
  166. else return 0;
  167. }
  168. else
  169. {
  170. second_best = (float)best_alignments.second_score();
  171. // if (info)
  172. // info->second_best = (int32)second_best;
  173. const float best_diff = fabsf(fabsf( best ) - fabsf( second_best ));
  174. if (best_diff >= diff * 0.9f)
  175. return (best_over == diff) ? 39 : 33;
  176. else if (best_diff >= diff * 0.8f)
  177. return (best_over == diff) ? 38 : 27;
  178. else if (best_diff >= diff * 0.7f)
  179. return (best_over == diff) ? 37 : 26;
  180. else if (best_diff >= diff * 0.6f)
  181. return (best_over == diff) ? 36 : 22;
  182. else if (best_diff >= diff * 0.5f)
  183. {
  184. // top third is still pretty good
  185. if (best_over == diff) return 35;
  186. else if (best_over >= diff * 0.84f) return 25;
  187. else if (best_over >= diff * 0.68f) return 16;
  188. else return 5;
  189. }
  190. else if (best_diff >= diff * 0.4f)
  191. {
  192. // top third is still pretty good
  193. if (best_over == diff) return 34;
  194. else if (best_over >= diff * 0.84f) return 21;
  195. else if (best_over >= diff * 0.68f) return 14;
  196. else return 4;
  197. }
  198. else if (best_diff >= diff * 0.3f)
  199. {
  200. // top third is still pretty good
  201. if (best_over == diff) return 32;
  202. else if (best_over >= diff * 0.88f) return 18;
  203. else if (best_over >= diff * 0.67f) return 15;
  204. else return 3;
  205. }
  206. else if (best_diff >= diff * 0.2f)
  207. {
  208. // top third is still pretty good
  209. if (best_over == diff) return 31;
  210. else if (best_over >= diff * 0.88f) return 17;
  211. else if (best_over >= diff * 0.67f) return 11;
  212. else return 0;
  213. }
  214. else if (best_diff >= diff * 0.1f)
  215. {
  216. // top third is still pretty good
  217. if (best_over == diff) return 30;
  218. else if (best_over >= diff * 0.88f) return 12;
  219. else if (best_over >= diff * 0.67f) return 7;
  220. else return 0;
  221. }
  222. else if (best_diff > 0)
  223. {
  224. // top third is still pretty good
  225. return (best_over >= diff * 0.67f) ? 6 : 2;
  226. }
  227. else
  228. {
  229. // top third is still pretty good
  230. return (best_over >= diff * 0.67f) ? 1 : 0;
  231. }
  232. }
  233. }
  234. else
  235. {
  236. // local alignment
  237. if (!has_second)
  238. {
  239. if (best_over >= diff * 0.8f) return 44;
  240. else if (best_over >= diff * 0.7f) return 42;
  241. else if (best_over >= diff * 0.6f) return 41;
  242. else if (best_over >= diff * 0.5f) return 36;
  243. else if (best_over >= diff * 0.4f) return 28;
  244. else if (best_over >= diff * 0.3f) return 24;
  245. else return 22;
  246. }
  247. else
  248. {
  249. second_best = (float)best_alignments.second_score();
  250. // if (info)
  251. // info->second_best = (int32)second_best;
  252. const float best_diff = fabsf(fabsf( best ) - fabsf( second_best ));
  253. if (best_diff >= diff * 0.9f) return 40;
  254. else if (best_diff >= diff * 0.8f) return 39;
  255. else if (best_diff >= diff * 0.7f) return 38;
  256. else if (best_diff >= diff * 0.6f) return 37;
  257. else if (best_diff >= diff * 0.5f)
  258. {
  259. if (best_over == diff) return 35;
  260. else if (best_over >= diff * 0.50f) return 25;
  261. else return 20;
  262. }
  263. else if (best_diff >= diff * 0.4f)
  264. {
  265. if (best_over == diff) return 34;
  266. else if (best_over >= diff * 0.50f) return 21;
  267. else return 19;
  268. }
  269. else if (best_diff >= diff * 0.3f)
  270. {
  271. if (best_over == diff) return 33;
  272. else if (best_over >= diff * 0.5f) return 18;
  273. else return 16;
  274. }
  275. else if (best_diff >= diff * 0.2f)
  276. {
  277. if (best_over == diff) return 32;
  278. else if (best_over >= diff * 0.5f) return 17;
  279. else return 12;
  280. }
  281. else if (best_diff >= diff * 0.1f)
  282. {
  283. if (best_over == diff) return 31;
  284. else if (best_over >= diff * 0.5f) return 14;
  285. else return 9;
  286. }
  287. else if (best_diff > 0)
  288. return (best_over >= diff * 0.5f) ? 11 : 2;
  289. else
  290. return (best_over >= diff * 0.5f) ? 1 : 0;
  291. }
  292. }
  293. }
  294. private:
  295. ScoringSchemeType m_sc;
  296. };
  297. } // namespace cuda
  298. } // namespace bowtie2
  299. } // namespace nvbio