Start of a huge refactoring
This commit is contained in:
@@ -15,6 +15,7 @@ obisys = { path = "../obisys" }
|
||||
obikindex = { path = "../obikindex", default-features = false }
|
||||
obikindexer = { path = "../obikindexer" }
|
||||
obikalgorithm = { path = "../obikalgorithm" }
|
||||
obikmerge = { path = "../obikmerge" }
|
||||
obifastwrite = { path = "../obifastwrite" }
|
||||
obiskbuilder = { path = "../obiskbuilder" }
|
||||
clap = { version = "4", features = ["derive"] }
|
||||
|
||||
@@ -0,0 +1,104 @@
|
||||
use std::path::PathBuf;
|
||||
|
||||
use clap::Args;
|
||||
use obikalgorithm::Algorithm;
|
||||
use obikindex::KmerIndex;
|
||||
use obikmerge::{Merge, MergeMode};
|
||||
use obisys::{Progress, Reporter, Stage, progress_bar};
|
||||
use tracing::info;
|
||||
|
||||
#[derive(Args)]
|
||||
pub struct MergeArgs {
|
||||
/// Source index directories to merge
|
||||
#[arg(required = true)]
|
||||
pub sources: Vec<PathBuf>,
|
||||
|
||||
/// Output index directory
|
||||
#[arg(short, long)]
|
||||
pub output: PathBuf,
|
||||
|
||||
/// Overwrite output directory if it already exists
|
||||
#[arg(long, default_value_t = false)]
|
||||
pub force: bool,
|
||||
|
||||
/// Force presence/absence mode even if all sources have count data
|
||||
#[arg(long, default_value_t = false)]
|
||||
pub force_presence: bool,
|
||||
|
||||
/// Disambiguate duplicate genome labels by appending .1, .2, … instead of erroring
|
||||
#[arg(long, default_value_t = false)]
|
||||
pub rename_duplicates: bool,
|
||||
}
|
||||
|
||||
pub fn run(args: MergeArgs) {
|
||||
let sources: Vec<KmerIndex> = args
|
||||
.sources
|
||||
.iter()
|
||||
.map(|p| {
|
||||
info!("opening source index: {}", p.display());
|
||||
KmerIndex::open(p).unwrap_or_else(|e| {
|
||||
eprintln!("error opening source index {}: {e}", p.display());
|
||||
std::process::exit(1);
|
||||
})
|
||||
})
|
||||
.collect();
|
||||
|
||||
// Auto-detect mode: count if all sources have count data, presence otherwise.
|
||||
// --force-presence overrides to presence regardless.
|
||||
let all_have_counts = sources.iter().all(|s| s.meta().config.with_counts);
|
||||
let mode = if !args.force_presence && all_have_counts {
|
||||
MergeMode::Count
|
||||
} else {
|
||||
MergeMode::Presence
|
||||
};
|
||||
info!(
|
||||
"merge mode: {}",
|
||||
if mode == MergeMode::Count {
|
||||
"count"
|
||||
} else {
|
||||
"presence/absence"
|
||||
}
|
||||
);
|
||||
|
||||
let source_refs: Vec<&KmerIndex> = sources.iter().collect();
|
||||
|
||||
let n_genomes: usize = sources
|
||||
.iter()
|
||||
.map(|s| {
|
||||
s.meta()
|
||||
.genomes()
|
||||
.unwrap_or_else(|e| {
|
||||
eprintln!("error reading index metadata: {e}");
|
||||
std::process::exit(1);
|
||||
})
|
||||
.len()
|
||||
})
|
||||
.sum();
|
||||
info!(
|
||||
"merging {} index(es), {} genome(s) total → {}",
|
||||
sources.len(),
|
||||
n_genomes,
|
||||
args.output.display()
|
||||
);
|
||||
|
||||
let mut rep = Reporter::new();
|
||||
let t = Stage::start("merge");
|
||||
let n_partitions = source_refs.first().map(|s| s.n_partitions()).unwrap_or(0);
|
||||
let pb = progress_bar("merge", n_partitions as u64, "partitions");
|
||||
|
||||
let mut merge = Merge::new(&source_refs, &args.output, mode)
|
||||
.force(args.force)
|
||||
.rename_duplicates(args.rename_duplicates)
|
||||
.on_progress(|_: Progress| pb.inc(1));
|
||||
|
||||
let dst = merge.run().unwrap_or_else(|e| {
|
||||
eprintln!("error merging: {e}");
|
||||
std::process::exit(1);
|
||||
});
|
||||
pb.finish_and_clear();
|
||||
rep.push(t.stop());
|
||||
|
||||
info!("merge done — output at {}", dst.dir().display());
|
||||
merge.reporter().print();
|
||||
rep.print();
|
||||
}
|
||||
@@ -1,2 +1,3 @@
|
||||
pub mod index;
|
||||
pub mod merge;
|
||||
pub mod superkmer;
|
||||
|
||||
@@ -17,6 +17,8 @@ enum Commands {
|
||||
Index(cmd::index::IndexArgs),
|
||||
/// Extract super-k-mers from input sequences and scatter them by partition
|
||||
Superkmer(cmd::superkmer::SuperkmerArgs),
|
||||
/// Merge multiple genome indexes into one
|
||||
Merge(cmd::merge::MergeArgs),
|
||||
}
|
||||
|
||||
fn main() {
|
||||
@@ -31,5 +33,6 @@ fn main() {
|
||||
match cli.command {
|
||||
Commands::Index(args) => cmd::index::run(args),
|
||||
Commands::Superkmer(args) => cmd::superkmer::run(args),
|
||||
Commands::Merge(args) => cmd::merge::run(args),
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user