use std::{env, time::Instant};
use anyhow::{Context, Result};
use env_logger::Builder;
use log::{LevelFilter, info};
use ndarray::Array2;
use crate::{
cli::{NeighbourNetArgs, ProgramArgs},
neighbour_net::neighbour_net::NeighbourNet,
nexus::nexus::Nexus,
};
pub mod algorithms;
pub mod cli;
pub mod data;
pub mod neighbour_net;
pub mod nexus;
pub mod ordering;
pub mod phylo;
pub mod splits;
pub mod utils;
pub mod weights;
#[cfg(test)]
pub(crate) mod test_helpers;
#[macro_use]
extern crate log;
pub fn set_log_level(matches: &ProgramArgs, is_last: bool, program_name: &str, version: &str) {
let mut log_level = LevelFilter::Info;
let mut specified = false;
if matches.verbose {
specified = true;
log_level = LevelFilter::Debug;
}
if matches.quiet {
specified = true;
log_level = LevelFilter::Error;
}
if specified || is_last {
let mut builder = Builder::new();
builder.filter_level(log_level);
if let Ok(rust_log) = env::var("RUST_LOG") {
builder.parse_filters(&rust_log);
}
let _ = builder.try_init();
}
if is_last {
info!("{} version {}", program_name, version);
}
}
pub fn run_fast_nnt_from_memory(
dist: Array2<f64>,
labels: Vec<String>,
args: NeighbourNetArgs,
) -> Result<Nexus> {
let t0 = Instant::now();
let neighbour_net = NeighbourNet::from_distance_matrix(dist, labels, args)
.context("Validating distance matrix")?;
let nexus = neighbour_net
.into_nexus()
.context("Performing neighbour net analysis")?;
info!("Finished NeighbourNet in {:?}", t0.elapsed());
Ok(nexus)
}
pub enum RayonInitStatus {
Initialized,
AlreadyInitializedSame,
AlreadyInitializedDifferent { current: usize },
}
pub fn init_rayon_threads(threads: usize) -> Result<RayonInitStatus> {
if threads == 0 {
return Ok(RayonInitStatus::Initialized);
}
match rayon::ThreadPoolBuilder::new()
.num_threads(threads)
.build_global()
{
Ok(()) => Ok(RayonInitStatus::Initialized),
Err(e) => {
let msg = e.to_string();
if msg.contains("global thread pool has already been initialized") {
let current = rayon::current_num_threads();
if current == threads {
Ok(RayonInitStatus::AlreadyInitializedSame)
} else {
Ok(RayonInitStatus::AlreadyInitializedDifferent { current })
}
} else {
Err(e.into())
}
}
}
}