lib.rs 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. use anyhow::Result;
  2. use minimap2::{Alignment, Mapping, Strand};
  3. use serde::{Deserialize, Serialize};
  4. use serde_nested_with::serde_nested;
  5. use std::num::NonZeroI32;
  6. use tokio::runtime::Builder;
  7. pub fn get_mappings(url: &str, sequence: String) -> Result<Vec<Mapping>> {
  8. let runtime = Builder::new_multi_thread()
  9. .worker_threads(1)
  10. .enable_all()
  11. .build()?;
  12. let res = runtime.block_on(get_mappings_async(url.to_string(), sequence))?;
  13. // let handle = runtime.spawn(get_mappings_async(url.to_string(), sequence));
  14. // let res = runtime.block_on(handle)??;
  15. Ok(res)
  16. }
  17. pub async fn get_mappings_async(url: String, sequence: String) -> Result<Vec<Mapping>> {
  18. let client = reqwest::Client::new();
  19. let url = reqwest::Url::parse(&url).unwrap();
  20. let response = client.post(url).body(sequence).send().await.unwrap();
  21. let response_body = response.text().await.unwrap();
  22. let mappings: Mappings = serde_json::from_str(&response_body).unwrap();
  23. Ok(mappings.inner)
  24. }
  25. #[derive(Serialize, Deserialize, Debug)]
  26. #[serde(remote = "Strand")]
  27. enum StrandDef {
  28. Forward,
  29. Reverse,
  30. }
  31. #[derive(Serialize, Deserialize, Debug)]
  32. #[serde(remote = "Alignment")]
  33. struct AlignmentDef {
  34. pub nm: i32,
  35. pub cigar: Option<Vec<(u32, u8)>>,
  36. pub cigar_str: Option<String>,
  37. pub md: Option<String>,
  38. pub cs: Option<String>,
  39. }
  40. #[serde_nested]
  41. #[derive(Serialize, Deserialize, Debug)]
  42. #[serde(remote = "Mapping")]
  43. pub struct MappingDef {
  44. query_name: Option<String>,
  45. query_len: Option<NonZeroI32>,
  46. query_start: i32,
  47. query_end: i32,
  48. #[serde(with = "StrandDef")]
  49. strand: Strand,
  50. target_name: Option<String>,
  51. target_len: i32,
  52. target_start: i32,
  53. target_end: i32,
  54. match_len: i32,
  55. block_len: i32,
  56. mapq: u32,
  57. is_primary: bool,
  58. is_supplementary: bool,
  59. #[serde_nested(sub = "Alignment", serde(with = "AlignmentDef"))]
  60. alignment: Option<Alignment>,
  61. }
  62. #[serde_nested]
  63. #[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
  64. pub struct Mappings {
  65. #[serde_nested(
  66. sub = "Mapping",
  67. serde(
  68. serialize_with = "MappingDef::serialize",
  69. deserialize_with = "MappingDef::deserialize"
  70. )
  71. )]
  72. pub inner: Vec<Mapping>,
  73. }
  74. pub fn dist_align(url: String) -> impl Fn(String) -> Result<Vec<Mapping>> {
  75. move |sequence: String| -> Result<Vec<Mapping>> { get_mappings(url.as_str(), sequence) }
  76. }
  77. #[cfg(test)]
  78. mod tests {
  79. use super::*;
  80. #[test]
  81. fn it_works() {
  82. let url = "http://localhost:4444/align".to_string();
  83. let aligner = dist_align(url);
  84. let mut mappings =
  85. aligner("CCAAAACACATATTCACGGCAGCCACTCCACCCAGCACCTCaca".to_string()).unwrap();
  86. let mapping = mappings.pop().unwrap();
  87. assert_eq!(mapping.target_name.unwrap(), "chr6".to_string());
  88. }
  89. }