rayon/
rayon.rs

1use clap::Parser;
2use minimap2::*;
3use needletail::{FastxReader, parse_fastx_file};
4use rayon::prelude::*;
5
6use std::path::PathBuf;
7use std::{error::Error, path::Path};
8
9#[derive(Parser, Debug)]
10#[command(
11    name = "minimap2-channels-example",
12    about = "An example of how to use the minimap2 crate with multithreading"
13)]
14struct Cli {
15    /// The target file to align to (e.g. a reference genome - can be in FASTA, FASTQ, or mmi format)
16    pub target: PathBuf,
17
18    /// The query file to align (e.g. reads - can be FASTA or FASTQ)
19    pub query: PathBuf,
20
21    /// The number of threads to use
22    pub threads: usize,
23}
24
25fn main() {
26    // Parse command line arguments
27    let args = Cli::parse();
28
29    map(args.target, args.query, args.threads).expect("Unable to map");
30}
31
32fn map(
33    target_file: impl AsRef<Path>,
34    query_file: impl AsRef<Path>,
35    threads: usize,
36) -> Result<(), Box<dyn Error>> {
37    // Set the number of threads to use
38    rayon::ThreadPoolBuilder::new()
39        .num_threads(threads)
40        .build_global()
41        .expect("Unable to set number of threads");
42
43    println!("Creating index");
44
45    // Aligner gets created using the build pattern.
46    // Once .with_index is called, the aligner is set to "Built" and can no longer be changed.
47    let aligner = Aligner::builder()
48        .map_ont()
49        .with_cigar()
50        .with_index_threads(threads) // Minimap2 uses it's own thread pool for index building
51        .with_index(target_file, None)
52        .expect("Unable to build index");
53
54    println!("Index created");
55
56    // Read in the query file
57    let mut reader = parse_fastx_file(query_file)?;
58
59    let mut queries: Vec<(Vec<u8>, Vec<u8>)> = Vec::new();
60    while let Some(record) = reader.next() {
61        let record = record.expect("Error reading record");
62        queries.push((record.id().to_vec(), record.seq().to_vec()));
63    }
64
65    // Map the queries
66    let results: Vec<Vec<Mapping>> = queries
67        .par_iter()
68        .map(|(id, seq)| {
69            aligner
70                .map(&seq, false, false, None, None, Some(&id))
71                .expect("Error mapping")
72        })
73        .collect();
74
75    // Count total number of alignments
76    let total_alignments: usize = results.iter().map(|x| x.len()).sum();
77    println!("Iteration complete, total alignments {}", total_alignments);
78
79    Ok(())
80}