Browse Source

first commit

Thomas 1 year ago
commit
19b2d21744
5 changed files with 565 additions and 0 deletions
  1. 1 0
      .gitignore
  2. 302 0
      Cargo.lock
  3. 12 0
      Cargo.toml
  4. 202 0
      src/lib.rs
  5. 48 0
      test_data/419b7353-bc8c-4ffe-8ad6-0bbfac8c0cfa.fasta

+ 1 - 0
.gitignore

@@ -0,0 +1 @@
+/target

+ 302 - 0
Cargo.lock

@@ -0,0 +1,302 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
+
+[[package]]
+name = "aho-corasick"
+version = "1.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
+name = "anyhow"
+version = "1.0.86"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da"
+
+[[package]]
+name = "env_logger"
+version = "0.10.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4cd405aab171cb85d6735e5c8d9db038c17d3ca007a4d2c25f337935c3d90580"
+dependencies = [
+ "humantime",
+ "is-terminal",
+ "log",
+ "regex",
+ "termcolor",
+]
+
+[[package]]
+name = "hermit-abi"
+version = "0.3.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024"
+
+[[package]]
+name = "humantime"
+version = "2.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
+
+[[package]]
+name = "is-terminal"
+version = "0.4.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f23ff5ef2b80d608d61efee834934d862cd92461afc0560dedf493e4c033738b"
+dependencies = [
+ "hermit-abi",
+ "libc",
+ "windows-sys",
+]
+
+[[package]]
+name = "itoa"
+version = "1.0.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b"
+
+[[package]]
+name = "libc"
+version = "0.2.155"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c"
+
+[[package]]
+name = "log"
+version = "0.4.22"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24"
+
+[[package]]
+name = "memchr"
+version = "2.7.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
+
+[[package]]
+name = "pandora_lib_blastn"
+version = "0.1.0"
+dependencies = [
+ "anyhow",
+ "env_logger",
+ "log",
+ "serde",
+ "serde_json",
+ "thiserror",
+]
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.86"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77"
+dependencies = [
+ "unicode-ident",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.36"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "regex"
+version = "1.10.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b91213439dad192326a0d7c6ee3955910425f441d7038e0d6933b0aec5c4517f"
+dependencies = [
+ "aho-corasick",
+ "memchr",
+ "regex-automata",
+ "regex-syntax",
+]
+
+[[package]]
+name = "regex-automata"
+version = "0.4.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df"
+dependencies = [
+ "aho-corasick",
+ "memchr",
+ "regex-syntax",
+]
+
+[[package]]
+name = "regex-syntax"
+version = "0.8.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b"
+
+[[package]]
+name = "ryu"
+version = "1.0.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f"
+
+[[package]]
+name = "serde"
+version = "1.0.204"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bc76f558e0cbb2a839d37354c575f1dc3fdc6546b5be373ba43d95f231bf7c12"
+dependencies = [
+ "serde_derive",
+]
+
+[[package]]
+name = "serde_derive"
+version = "1.0.204"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e0cd7e117be63d3c3678776753929474f3b04a43a080c744d6b0ae2a8c28e222"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "serde_json"
+version = "1.0.120"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4e0d21c9a8cae1235ad58a00c11cb40d4b1e5c784f1ef2c537876ed6ffd8b7c5"
+dependencies = [
+ "itoa",
+ "ryu",
+ "serde",
+]
+
+[[package]]
+name = "syn"
+version = "2.0.70"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2f0209b68b3613b093e0ec905354eccaedcfe83b8cb37cbdeae64026c3064c16"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "termcolor"
+version = "1.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755"
+dependencies = [
+ "winapi-util",
+]
+
+[[package]]
+name = "thiserror"
+version = "1.0.61"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709"
+dependencies = [
+ "thiserror-impl",
+]
+
+[[package]]
+name = "thiserror-impl"
+version = "1.0.61"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "unicode-ident"
+version = "1.0.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
+
+[[package]]
+name = "winapi-util"
+version = "0.1.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4d4cc384e1e73b93bafa6fb4f1df8c41695c8a91cf9c4c64358067d15a7b6c6b"
+dependencies = [
+ "windows-sys",
+]
+
+[[package]]
+name = "windows-sys"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
+dependencies = [
+ "windows-targets",
+]
+
+[[package]]
+name = "windows-targets"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
+dependencies = [
+ "windows_aarch64_gnullvm",
+ "windows_aarch64_msvc",
+ "windows_i686_gnu",
+ "windows_i686_gnullvm",
+ "windows_i686_msvc",
+ "windows_x86_64_gnu",
+ "windows_x86_64_gnullvm",
+ "windows_x86_64_msvc",
+]
+
+[[package]]
+name = "windows_aarch64_gnullvm"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
+
+[[package]]
+name = "windows_aarch64_msvc"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
+
+[[package]]
+name = "windows_i686_gnu"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
+
+[[package]]
+name = "windows_i686_gnullvm"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
+
+[[package]]
+name = "windows_i686_msvc"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
+
+[[package]]
+name = "windows_x86_64_gnu"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
+
+[[package]]
+name = "windows_x86_64_gnullvm"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
+
+[[package]]
+name = "windows_x86_64_msvc"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"

+ 12 - 0
Cargo.toml

@@ -0,0 +1,12 @@
+[package]
+name = "pandora_lib_blastn"
+version = "0.1.0"
+edition = "2021"
+
+[dependencies]
+thiserror = "^1.0.50"
+log = "^0.4.20"
+env_logger = "^0.10.1"
+anyhow = "^1.0.75"
+serde_json = "1.0.120"
+serde = { version = "1.0.204", features = ["derive"] }

+ 202 - 0
src/lib.rs

@@ -0,0 +1,202 @@
+use std::{
+    fs::{self, File},
+    io::Write,
+    process::{Command, Stdio},
+};
+
+use anyhow::{Context, Ok};
+use log::info;
+use serde::{Deserialize, Serialize};
+
+// cat /home/prom/Documents/Programmes/desc_seq_lib/data_test/419b7353-bc8c-4ffe-8ad6-0bbfac8c0cfa.fasta | blastn -db hs1_simple_chr.fa -outfmt 6
+pub fn run_blastn(query_fa_path: &str) -> anyhow::Result<String> {
+    info!("Running blastn in {query_fa_path}");
+    let blastn_bin = "/usr/bin/blastn";
+    let blast_db = "/data/ref/hs1/hs1_simple_chr.fa";
+
+    let file_contents = fs::read_to_string(query_fa_path).context("Failed to read the file")?;
+
+    let mut cmd = Command::new(blastn_bin)
+        .arg("-db")
+        .arg(blast_db)
+        .arg("-outfmt")
+        .arg("6")
+        .arg("-num_threads")
+        .arg("6")
+        .stdin(Stdio::piped())
+        .stdout(Stdio::piped())
+        .spawn()
+        .expect("Blastn failed to start");
+
+    {
+        let stdin = cmd.stdin.as_mut().expect("Failed to open stdin");
+        stdin
+            .write_all(file_contents.as_bytes())
+            .expect("Failed to write to stdin");
+    }
+
+    let output = cmd.wait_with_output().expect("Failed to read stdout");
+
+    Ok(String::from_utf8_lossy(&output.stdout).to_string())
+}
+
+pub fn parse_blastn_touput(output: String) -> Vec<BlastResult> {
+    let mut lines: Vec<&str> = output.split("\n").collect();
+
+    let mut results = Vec::new();
+    for line in lines.drain(..) {
+        if let std::result::Result::Ok(r) = line.to_string().try_into() {
+            results.push(r);
+        }
+    }
+    results
+}
+
+#[derive(Debug, Clone, Serialize, Deserialize)]
+pub struct BlastResult {
+    pub query_id: String,
+    pub subject_id: String,
+    pub percent_identity: f64,
+    pub alignment_length: usize,
+    pub mismatches: usize,
+    pub gap_opens: usize,
+    pub q_start: usize,
+    pub q_end: usize,
+    pub s_start: usize,
+    pub s_end: usize,
+    pub e_value: f64,
+    pub bit_score: f64,
+}
+
+impl TryFrom<String> for BlastResult {
+    type Error = anyhow::Error;
+
+    fn try_from(line: String) -> anyhow::Result<Self> {
+        let fields: Vec<&str> = line.split('\t').collect();
+
+        if fields.len() != 12 {
+            return Err(anyhow::anyhow!(
+                "Expected 12 fields, but got {}",
+                fields.len()
+            ));
+        }
+
+        Ok(BlastResult {
+            query_id: fields[0].to_string(),
+            subject_id: fields[1].to_string(),
+            percent_identity: fields[2]
+                .parse()
+                .context("Failed to parse percent_identity")?,
+            alignment_length: fields[3]
+                .parse()
+                .context("Failed to parse alignment_length")?,
+            mismatches: fields[4].parse().context("Failed to parse mismatches")?,
+            gap_opens: fields[5].parse().context("Failed to parse gap_opens")?,
+            q_start: fields[6].parse().context("Failed to parse q_start")?,
+            q_end: fields[7].parse().context("Failed to parse q_end")?,
+            s_start: fields[8].parse().context("Failed to parse s_start")?,
+            s_end: fields[9].parse().context("Failed to parse s_end")?,
+            e_value: fields[10].parse().context("Failed to parse e_value")?,
+            bit_score: fields[11].parse().context("Failed to parse bit_score")?,
+        })
+    }
+}
+
+pub fn blastn(fa_path: &str, output_json: &str) -> anyhow::Result<()> {
+    let res = run_blastn(fa_path)?;
+    let mut res = parse_blastn_touput(res);
+    res.sort_by(|a, b| b.bit_score.total_cmp(&a.bit_score));
+    let json = serde_json::to_string(&res)?;
+    let mut file = File::create(output_json)?;
+    file.write_all(json.as_bytes())?;
+    Ok(())
+}
+
+#[derive(Debug)]
+struct BlastPile {
+    x: usize,
+    length: usize,
+    y: usize,
+    data: BlastResult,
+}
+
+impl BlastPile {
+    pub fn new(d: &BlastResult) -> BlastPile {
+        BlastPile {
+            x: d.q_start,
+            length: d.q_end - d.q_start,
+            y: 0,
+            data: d.clone(),
+        }
+    }
+}
+
+fn sort_blast_pile(objects: &mut Vec<BlastPile>) {
+    objects.sort_by(|a, b| a.x.partial_cmp(&b.x).unwrap());
+}
+
+fn allocate_y_positions(objects: &mut Vec<BlastPile>) {
+    sort_blast_pile(objects);
+
+    let mut active_intervals: Vec<(usize, usize)> = vec![]; // Stores (x + length, y) tuples
+
+    for obj in objects.iter_mut() {
+        let mut y_position = 0;
+
+        // Find the lowest y position where it does not overlap
+        loop {
+            let overlap = active_intervals
+                .iter()
+                .any(|(end_x, y)| *y == y_position && obj.x < *end_x);
+            if !overlap {
+                break;
+            }
+            y_position += 1;
+        }
+
+        // Assign the y position
+        obj.y = y_position;
+
+        // Add the current object to active intervals
+        active_intervals.push((obj.x + obj.length, obj.y));
+
+        // Remove intervals that are no longer active
+        active_intervals.retain(|(end_x, _)| obj.x < *end_x);
+    }
+}
+
+pub fn best_blastn(fa_path: &str) -> anyhow::Result<Vec<BlastResult>> {
+    let res = run_blastn(fa_path)?;
+    let mut results: Vec<BlastPile> = parse_blastn_touput(res)
+        .iter()
+        .take(1000)
+        .map(|v| BlastPile::new(v))
+        .collect();
+    allocate_y_positions(&mut results);
+    let results: Vec<BlastResult> = results
+        .into_iter()
+        .filter(|r| r.y == 0)
+        .map(|r| r.data)
+        .collect();
+    Ok(results)
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    #[test]
+    fn best() -> anyhow::Result<()> {
+        let _ = env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("info"))
+            .build();
+
+        let fa = "test_data/419b7353-bc8c-4ffe-8ad6-0bbfac8c0cfa.fasta";
+
+        let res = best_blastn(fa)?;
+
+        assert_eq!(res[0].q_end, 2838);
+        assert_eq!(res[1].q_start, 2935);
+
+        Ok(())
+    }
+}

+ 48 - 0
test_data/419b7353-bc8c-4ffe-8ad6-0bbfac8c0cfa.fasta

@@ -0,0 +1,48 @@
+>419b7353-bc8c-4ffe-8ad6-0bbfac8c0cfa
+TAACTCGTCATTTACATTAGGTATAACTCCTAATGGTATCCCTCCCCCACCCCCCACCCCACAACAGGCCCCAGTGTGTG
+ATGTTCCCCTTCCTGTGTCCAAGTGTTCTCATTGTTCAATTCCCACCTATGAGTGAGAACATGCAGTGTTCACTATGGAG
+TCTTCTAGGTACAAAATCATGTTTGTGAAGAGAGATAGTTGACTTCTTTTTTTTCTATTTGGAAACCTTTATTTCTTTCA
+CTTGCCTTATTGCTCTGGCTAGGACGTCCAGTACTATGTTGATTAGGAGTGGTGAGAGTGGGCATCTTGGTCTTGTTTCA
+GTTCTCACGGGGAATGCTTCCAGCTTTTGCCTGTTGAGTATGATGTTAGCTGTGGGCTTGTCAAAGATGGCTCTTATTAT
+TTTGAAGTATGCTACTTCAATACCTAGTTTTTTTTTTTTTTTTTTAACATGAAAGGATGTTGAATTTTATCAAAAGTCTT
+TTCTGCATTTATTGAAATGATAATGTGGTATTTGTTTTTTGCTTTGCTTTTGTGACAAATCATATTTATTGATTTGTGTA
+CATTGAACCAACCTTGCAGAACAAGAATAAAGGCTACTTGATCATGGTGGATTAGCTTTTTGATACAATGCTGGATTTCG
+TTTGCTAGCATTTTGTTGAGTATTTTTGTATACATGTTCACCAGGAATGTTGGCCAGAATTTCTGTGTGTGTGTGTGTGT
+GTGTGTGTGTATCAGAATGATGCTAGCCTTATAGAATAAGTTAGAGAGGAGTCCCTCCTCCTTTGATTTTTTTTTTTTGA
+ATAGTTTCAGTAGGATTGGTAATACCTTTTGTTTTTTACATATGGTAGAATTCAGCTGTGAAGTCCATCTAATCTAAGGC
+TTTTTCTGTTTGACAGGTTTTTGTTACTGATTCAATTTTGGAACTCATTAATGGTCTGTTCAGGGTTTCAATTTTTTCCA
+GGTTTAATCTTGAGAGGTTGTACGTTTCCCAGAATTTATCCATTCCTTCTAGGTTTTCTAGTTTATGTGCACAGAAGTGT
+TCATTTAGTCTTTGAGGGTTTTTTATATTTCTGTGGGGTTGATGGTAATGTCCCTTTGGTCATTTCCGATTGTCTTTATT
+TAGATCTTCTCTCTTTTTTGTAAGTCTAGCAAGCACTCTTTCAATCTTATTTATTTTTTCAGAAAACCAACGTTTGGTTT
+CATTGATGTTTGAAAACAATTGTATGTATTTTGCACATTAACTTTGTTAAGTTCTGATTTTGGTTATTTCTTTTCTCCTT
+CTATCTTTTGGGTTGGTTTGCTCTTGTTTTTCTACATCCTCTTGGTATAATGTTAGATTGTTTATTTGAGATTATTTGTG
+TTTTTGTTTTTGTACCAGTGCTGATATGGTTTGGATCTGTGTTCCCACCCAAACCTCACCTTGAATTGTAATCCCCATGA
+TCCCCATGTGTCAAGGGCAGGACCAGGTGGAGGTAATTGGATTGGCAATTTTAATGTCAGCATTTAGCACTGTACATTTT
+CCTCTTAACACTGCTTTCACCATGTCCCAGAGATTCTGGTATGTTGTACTTTTGTTTTCATTATTTTCAAAGAATTTCTT
+GATTTCTGCCTTAATTTCATTGCTTAGCCAAAAGCCATTAAGGAGAAGGTTGTTTAATTTCCATGTAATTGTATAATTTT
+GAAATATCTTTTCACTATTGATTTCTATTTTCATTGCACTGTGGTCCGAGAGTGTAGGTTGGTATGATTTTATTTTTGAA
+TTTGTTGAGAATTGCTTTATGGTCAAGATGTGGTTCATTTTAGTCTATATGCCATGTGCAGATGAGAAGAATGTATATTC
+TGTTGTTGTTGGGTGGAGTGTGCTGCAGATGTCTGTCAGGTCCATTTGTTCAAGTGTCAAGTTTAGGTCCTGAATATCTT
+TGTTAATTCTCTGCCTCAATGATCTGTCTAACACTGTCAGTGGGGTGTTTTAGTGTCTCCCACTATTATTTTGTGGGAAT
+CTAAGTCTCTTTGTGGAATCAAGGTCTTTAAGAACTTGTCTTATAAATCTGAGTGCTTCAGTATTGGCTGCATATATATT
+TAGGATAATTAAGTCTTCCTGTGGAATTAAACCCTTTATCATTATATAATGCCCTTGTCTTTTTTTATCATTGTTGGTTT
+AAGGTCTGTTTTGTCTGAAATAAGAATAGCAACCCCTACTCTTCTCTCTGTTTTTCCTTTGCTTGGTAGATTTTTCTCCA
+TCCCTTTATTTTGAGCCTATGGGTGTCACTGCATATGAGATGGGTATCTTGAAGATAGCATAGAGTTGAGTCTTGCTTCT
+TTATCCAAATTGCCACTGTGTGCCTTTTAAGTGGGGCATTTAACCCATTTATACTCAAGGTTAATATTACTATGTGCAGA
+TTTGTTCCTGTCATTGTATTGTTAGCTGGTGGCTATGCAAACTTGATTGTGTAGTTGCTTTATAATGTAAACAGTCTATA
+TACTTAAGTGTGTTTTTATGGTGGCTGGTAACAGTCTTTTGATTCTGCATTTAGCACTTCCTTTAGGACTTGTATGGTAA
+GTCTGATGGTAACAAATTCCCTTAGCATTTGCTTTTCTGAAAAAGATTTTATTTCTCGTTTTCTTATGAAGCTTAGTTTG
+GCTGGATAAAATTCTTGGTTAAAATTTCTTTTCTTTAAGAATGTTGAATATAGGCCACATTCTCTTCTGGCTTACAGTGT
+TTCTGCTGAAAGGTCCATTGTTAGCCTGATGGGGGTCCCTTTGTCAGTGACCTTCCTATTCTCTCTAGCTGCTTTTAGTA
+TTTTTTTCTTTTGTGTTGACGCTGGAGAATCTGATAACAAAATCTTTTTCAGAAAATTCAAATGAGGAAAGAGCCATTAT
+AGATGAAAACTGGTCAGTTTTCAACTTTTCATTATAATGGCTCTTGAAAAGTTACACTATGGTTTTGTTTGTTTGTTTTT
+TTGTTTGGCTGGTTGGTTGATTTTTTTGTTTGAGACGGAGTCTTGCTCTGTCACCCAGGCTGGAGTGCAGGGGCGCAATC
+TCAGCTCACTGCCACCTCCACCTCCTGGGTTCAAGCGATTCTCCTGCCTCAGCCTTCCAAGTAGCTGGGACTACAGGTGC
+GTGTCACCACACCCAGCTAATTTTTGTATTTTTAGTAGAGACAGGGTTTTACCATACTGGCAACACTGGTCTCGAACTCC
+TGACCTCGTGATCCACCCACCTCAACCTCCCAAAGTGCTGGGATTACAGGCATGAGCCACCGCGCCTGGCCCCATGTTTT
+ATATAATGATTTCTTTGACATTCTCCCTGTGTAATGACTATTCACCCAAAGCACAATAAATATGTAAGAGTGCTATGTCT
+ACAATATTGCTTGAGGCAAATACACTCTATTTGCTGGTCACTGCGAATTCTAAGCAGAGAATATCATATAGAAAATATAA
+ATTGTGCCCTATTTTTGAATGAACCAAAAAAATGCTTTTCCTTGAGTACATACACCAAACAGGAGGAATACTGGTACAAA
+AGTAGATACATATACCAGTGGTACAGAAATAAAGGCAAATACTTAAAACAAACTGATCTTTCACAAAACATACAACAATA
+TAAACTGGGAAAAGGACACCTTATTCAATAAATCATTCTGGGGAAACTGGATAGCTACATGTAGAAGAATAAAACTGGAT
+CCCTATCTCTAACCTCATATAAAAAATCAACTTAAGGTGGATTAAG