use bed_reader::allclose;
use bed_reader::assert_eq_nan;
use bed_reader::assert_error_variant;
use bed_reader::sample_bed_file;
use bed_reader::sample_file;
use bed_reader::sample_files;
use bed_reader::Bed;
use bed_reader::BedError;
use bed_reader::BedErrorPlus;
use bed_reader::Metadata;
use bed_reader::MetadataFields;
use bed_reader::ReadOptions;
use bed_reader::SliceInfo1;
use bed_reader::WriteOptions;
use ndarray as nd;
use ndarray::s;
use ndarray_rand::{rand::prelude::StdRng, rand::SeedableRng, rand_distr::Uniform, RandomExt};
use std::collections::HashSet;
use std::panic::catch_unwind;
use temp_testdir::TempDir;
#[test]
fn rusty_bed1() -> Result<(), Box<BedErrorPlus>> {
let file = sample_bed_file("plink_sim_10s_100v_10pmiss.bed")?;
let mut bed = Bed::new(&file)?;
let val = bed.read::<i8>()?;
let mean = val.mapv(|elem| elem as f64).mean().unwrap();
assert!(mean == -13.142);
let mut bed = Bed::new(&file)?;
let val = ReadOptions::builder().count_a2().i8().read(&mut bed)?;
let mean = val.mapv(|elem| elem as f64).mean().unwrap();
assert!(mean == -13.274); Ok(())
}
#[test]
fn rusty_bed2() -> Result<(), Box<BedErrorPlus>> {
let file = sample_bed_file("plink_sim_10s_100v_10pmiss.bed")?;
let mut bed = Bed::new(file)?;
let val = ReadOptions::builder()
.iid_index(0)
.sid_index(vec![1])
.i8()
.read(&mut bed)?;
let mean = val.mapv(|elem| elem as f64).mean().unwrap();
println!("{mean:?}");
assert!(mean == 1.0);
Ok(())
}
#[test]
fn rusty_bed3() -> Result<(), Box<BedErrorPlus>> {
let file = sample_bed_file("plink_sim_10s_100v_10pmiss.bed")?;
let mut bed = Bed::new(file)?;
let iid_bool: nd::Array1<bool> = (0..bed.iid_count()?).map(|elem| (elem % 2) != 0).collect();
let sid_bool: nd::Array1<bool> = (0..bed.sid_count()?).map(|elem| (elem % 8) != 0).collect();
let val = ReadOptions::builder()
.missing_value(-127)
.iid_index(iid_bool)
.sid_index(sid_bool)
.read(&mut bed)?;
let mean = val.mapv(|elem| elem as f64).mean().unwrap();
println!("{mean:?}");
assert!(mean == -14.50344827586207);
Ok(())
}
#[test]
fn rusty_bed_allele() -> Result<(), Box<BedErrorPlus>> {
let file = sample_bed_file("plink_sim_10s_100v_10pmiss.bed")?;
let mut bed = Bed::new(file)?;
let val = ReadOptions::builder().count_a2().i8().read(&mut bed)?;
let mean = val.mapv(|elem| elem as f64).mean().unwrap();
println!("{mean:?}");
assert!(mean == -13.274);
Ok(())
}
#[test]
fn rusty_bed_order() -> Result<(), Box<BedErrorPlus>> {
let file = sample_bed_file("plink_sim_10s_100v_10pmiss.bed")?;
let mut bed = Bed::new(file)?;
let val = ReadOptions::builder().c().i8().read(&mut bed)?;
let mean = val.mapv(|elem| elem as f64).mean().unwrap();
println!("{mean:?}");
assert!(mean == -13.142);
Ok(())
}
#[test]
fn bad_header() -> Result<(), Box<BedErrorPlus>> {
let filename = sample_file("badfile.bed")?;
let bed = Bed::builder(&filename).skip_early_check().build()?;
println!("{:?}", bed.path());
let result = Bed::new(&filename);
assert_error_variant!(result, BedErrorPlus::BedError(BedError::IllFormed(_)));
Ok(())
}
#[test]
fn doc_test_test() -> Result<(), Box<BedErrorPlus>> {
let file_name = sample_bed_file("small.bed")?;
let mut bed = Bed::new(file_name)?;
let val = bed.read::<f64>()?;
assert_eq_nan(
&val,
&nd::array![
[1.0, 0.0, f64::NAN, 0.0],
[2.0, 0.0, f64::NAN, 2.0],
[0.0, 1.0, 2.0, 0.0]
],
);
let file_name2 = sample_bed_file("some_missing.bed")?;
let mut bed2 = Bed::new(&file_name2)?;
let val2 = ReadOptions::builder()
.f64()
.iid_index(s![..;2])
.sid_index(20..30)
.read(&mut bed2)?;
assert!(val2.dim() == (50, 10));
let mut bed3 = Bed::new(&file_name2)?;
println!("{:?}", bed3.iid()?.slice(s![..5]));
println!("{:?}", bed3.sid()?.slice(s![..5]));
println!("{:?}", bed3.chromosome()?.iter().collect::<HashSet<_>>());
let val3 = ReadOptions::builder()
.sid_index(bed3.chromosome()?.map(|elem| elem == "5"))
.f64()
.read(&mut bed3)?;
assert!(val3.dim() == (100, 6));
Ok(())
}
#[test]
fn open_examples() -> Result<(), Box<BedErrorPlus>> {
let file_name = sample_bed_file("small.bed")?;
let mut bed = Bed::new(&file_name)?;
println!("{:?}", bed.iid()?);
println!("{:?}", bed.sid()?);
println!("{:?}", bed.read::<f64>()?);
let mut bed = Bed::new(&file_name)?;
println!(
"{:?}",
ReadOptions::builder().sid_index(2).f64().read(&mut bed)?
);
let mut bed = Bed::builder(&file_name)
.iid(["sample1", "sample2", "sample3"])
.build()?;
println!("{:?}", bed.iid()?);
println!("{:?}", bed.sid()?);
let iid = nd::array!["sample1", "sample2", "sample3"];
let mut _bed = Bed::builder(&file_name).iid(iid).build()?;
let iid = nd::array![
"sample1".to_string(),
"sample2".to_string(),
"sample3".to_string()
];
let mut _bed = Bed::builder(&file_name).iid(iid).build()?;
let iid = vec!["sample1", "sample2", "sample3"];
let mut _bed = Bed::builder(&file_name).iid(iid).build()?;
let iid = vec![
"sample1".to_string(),
"sample2".to_string(),
"sample3".to_string(),
];
let mut _bed = Bed::builder(&file_name).iid(iid).build()?;
let mut bed = Bed::builder(&file_name).iid_count(3).sid_count(4).build()?;
println!("{:?}", bed.read::<f64>()?);
let mut bed = Bed::builder(&file_name).skip_allele_2().build()?;
println!("{:?}", bed.iid()?);
let result = bed.allele_2();
assert_error_variant!(
result,
BedErrorPlus::BedError(BedError::CannotUseSkippedMetadata(_))
);
Ok(())
}
#[test]
fn metadata_etc() -> Result<(), Box<BedErrorPlus>> {
let mut bed = Bed::new(sample_bed_file("small.bed")?)?;
println!("{:?}", bed.sex()?);
let mut bed = Bed::new(sample_bed_file("small.bed")?)?;
println!("{:?}", bed.cm_position()?);
println!("{:?}", bed.bp_position()?);
let mut bed = Bed::new(sample_bed_file("small.bed")?)?;
println!("{:?}", bed.fid()?);
println!("{:?}", bed.father()?);
println!("{:?}", bed.mother()?);
Ok(())
}
#[test]
fn hello_father() -> Result<(), Box<BedErrorPlus>> {
let mut bed = Bed::builder(sample_bed_file("small.bed")?)
.father(["f1", "f2", "f3"])
.skip_mother()
.build()?;
println!("{:?}", bed.father()?);
bed.mother().unwrap_err();
Ok(())
}
#[test]
fn num_threads() -> Result<(), Box<BedErrorPlus>> {
let file = sample_bed_file("plink_sim_10s_100v_10pmiss.bed")?;
let mut bed = Bed::new(file)?;
let val = ReadOptions::builder().num_threads(4).i8().read(&mut bed)?;
let mean = val.mapv(|elem| elem as f64).mean().unwrap();
println!("{mean:?}");
assert!(mean == -13.142);
Ok(())
}
#[test]
fn fam_and_bim() -> Result<(), Box<BedErrorPlus>> {
let deb_maf_mib = sample_files(["small.deb", "small.maf", "small.mib"])?;
let mut bed = Bed::builder(&deb_maf_mib[0])
.fam_path(&deb_maf_mib[1])
.bim_path(&deb_maf_mib[2])
.build()?;
println!("{:?}", bed.iid()?);
println!("{:?}", bed.sid()?);
let val: nd::Array2<i8> = bed.read()?;
let mean = val.mapv(|elem| elem as f64).mean().unwrap();
println!("{mean:?}");
assert!(mean == -20.5);
Ok(())
}
#[test]
fn readme_examples() -> Result<(), Box<BedErrorPlus>> {
let file_name = sample_bed_file("small.bed")?;
let mut bed = Bed::new(file_name)?;
let val = bed.read::<f64>()?;
println!("{val:?}");
let file_name2 = sample_bed_file("some_missing.bed")?;
let mut bed2 = Bed::new(&file_name2)?;
let val2 = ReadOptions::<f64>::builder()
.iid_index(s![..;2])
.sid_index(20..30)
.read(&mut bed2)?;
println!("{:?}", val2.dim());
let mut bed3 = Bed::new(&file_name2)?;
let iid = bed3.iid()?;
let s = iid.slice(s![..5]);
println!("{:?}", s);
println!("{:?}", bed3.iid()?.slice(s![..5]));
println!("{:?}", bed3.sid()?.slice(s![..5]));
let unique = bed3.chromosome()?.iter().collect::<HashSet<_>>();
println!("{unique:?}");
let is_5 = nd::Zip::from(bed3.chromosome()?).par_map_collect(|elem| elem == "5");
let val3 = ReadOptions::builder()
.sid_index(is_5)
.f64()
.read(&mut bed3)?;
println!("{:?}", val3.dim());
Ok(())
}
#[test]
fn write_docs() -> Result<(), Box<BedErrorPlus>> {
let output_folder = TempDir::default();
let output_file = output_folder.join("small.bed");
let val = nd::array![
[1.0, 0.0, f64::NAN, 0.0],
[2.0, 0.0, f64::NAN, 2.0],
[0.0, 1.0, 2.0, 0.0]
];
WriteOptions::builder(output_file)
.fid(["fid1", "fid1", "fid2"])
.iid(["iid1", "iid2", "iid3"])
.father(["iid23", "iid23", "iid22"])
.mother(["iid34", "iid34", "iid33"])
.sex([1, 2, 0])
.pheno(["red", "red", "blue"])
.chromosome(["1", "1", "5", "Y"])
.sid(["sid1", "sid2", "sid3", "sid4"])
.cm_position([100.4, 2000.5, 4000.7, 7000.9])
.bp_position([1, 100, 1000, 1004])
.allele_1(["A", "T", "A", "T"])
.allele_2(["A", "C", "C", "G"])
.write(&val)?;
let output_file2 = output_folder.join("small2.bed");
let val = nd::array![[1, 0, -127, 0], [2, 0, -127, 2], [0, 1, 2, 0]];
Bed::write(&val, &output_file2)?;
let mut bed2 = Bed::new(&output_file2)?;
println!("{:?}", bed2.chromosome()?);
Ok(())
}
#[test]
fn read_write() -> Result<(), Box<BedErrorPlus>> {
let file_name = sample_bed_file("small.bed")?;
let mut bed = Bed::new(file_name)?;
let val = bed.read::<f64>()?;
let metadata = bed.metadata()?;
println!("{metadata:?}");
let temp_out = TempDir::default();
let output_file = temp_out.join("small.deb");
let fam_file = temp_out.join("small.maf");
let bim_file = temp_out.join("small.mib");
WriteOptions::builder(&output_file)
.metadata(&metadata)
.fam_path(&fam_file)
.bim_path(&bim_file)
.write(&val)?;
assert!(
output_file.exists() & fam_file.exists() & bim_file.exists(),
"don't exist"
);
let mut deb = Bed::builder(&output_file)
.fam_path(&fam_file)
.bim_path(&bim_file)
.build()?;
let val2 = deb.read::<f64>()?;
let metadata2 = deb.metadata()?;
assert!(
allclose(&val.view(), &val2.view(), 1e-08, true),
"not close"
);
println!("{metadata:?}");
println!("{metadata2:?}");
assert!(metadata == metadata2, "meta not equal");
Ok(())
}
#[test]
fn range() -> Result<(), Box<BedErrorPlus>> {
let file_name = sample_bed_file("small.bed")?;
let mut bed = Bed::new(file_name)?;
ReadOptions::builder().iid_index(0..2).i8().read(&mut bed)?;
ReadOptions::builder()
.iid_index(0..=2)
.i8()
.read(&mut bed)?;
ReadOptions::builder().iid_index(..2).i8().read(&mut bed)?;
ReadOptions::builder().iid_index(..=2).i8().read(&mut bed)?;
ReadOptions::builder().iid_index(0..).i8().read(&mut bed)?;
ReadOptions::builder().iid_index(..).i8().read(&mut bed)?;
Ok(())
}
#[test]
fn nd_slice() -> Result<(), Box<BedErrorPlus>> {
let ndarray = nd::array![0, 1, 2, 3];
println!("{:?}", ndarray.slice(nd::s![1..3])); println!("{:?}", ndarray.slice(nd::s![1..3;-1])); #[allow(clippy::reversed_empty_ranges)]
let slice = nd::s![3..1;-1];
println!("{:?}", ndarray.slice(slice));
let file_name = sample_bed_file("small.bed")?;
let mut bed = Bed::new(file_name)?;
ReadOptions::builder()
.iid_index(nd::s![0..2])
.i8()
.read(&mut bed)?;
ReadOptions::builder()
.iid_index(nd::s![..2])
.i8()
.read(&mut bed)?;
ReadOptions::builder()
.iid_index(nd::s![0..])
.i8()
.read(&mut bed)?;
ReadOptions::builder()
.iid_index(nd::s![0..2])
.i8()
.read(&mut bed)?;
ReadOptions::builder()
.iid_index(nd::s![-2..-1;-1])
.i8()
.read(&mut bed)?;
Ok(())
}
#[test]
fn skip_coverage() -> Result<(), Box<BedErrorPlus>> {
let mut bed = Bed::builder(sample_bed_file("small.bed")?)
.skip_fid()
.skip_iid()
.skip_father()
.skip_mother()
.skip_sex()
.skip_pheno()
.skip_chromosome()
.skip_sid()
.skip_cm_position()
.skip_bp_position()
.skip_allele_1()
.skip_allele_2()
.build()?;
bed.mother().unwrap_err();
Ok(())
}
#[test]
fn into_iter() -> Result<(), Box<BedErrorPlus>> {
let file_name = sample_bed_file("small.bed")?;
let mut bed = Bed::builder(file_name)
.fid(["sample1", "sample2", "sample3"])
.iid(["sample1", "sample2", "sample3"])
.father(["sample1", "sample2", "sample3"])
.mother(["sample1", "sample2", "sample3"])
.sex([0, 0, 0])
.pheno(["sample1", "sample2", "sample3"])
.chromosome(["a", "b", "c", "d"])
.sid(["a", "b", "c", "d"])
.bp_position([0, 0, 0, 0])
.cm_position([0.0, 0.0, 0.0, 0.0])
.allele_1(["a", "b", "c", "d"])
.allele_2(["a", "b", "c", "d"])
.build()?;
let _ = bed.pheno()?;
Ok(())
}
#[allow(clippy::reversed_empty_ranges)]
#[test]
fn range_same() -> Result<(), Box<BedErrorPlus>> {
let a = rt1(3..0);
println!("{:?}", a);
let b = rt23((3..0).into());
println!("{:?}", b);
assert_same_result(rt1(3..0), rt23((3..0).into()));
assert_same_result(rt1(1000..), rt23((1000..).into()));
assert_same_result(rt1(..), rt23((..).into()));
assert_same_result(rt1(..3), rt23((..3).into()));
assert_same_result(rt1(..=3), rt23((..=3).into()));
assert_same_result(rt1(1..), rt23((1..).into()));
assert_same_result(rt1(1..3), rt23((1..3).into()));
assert_same_result(rt1(1..=3), rt23((1..=3).into()));
assert_same_result(rt1(2..=2), rt23((2..=2).into()));
Ok(())
}
#[test]
fn nd_slice_same() -> Result<(), Box<BedErrorPlus>> {
assert_same_result(nds1(s![1000..]), rt23(s![1000..].into()));
assert_same_result(nds1(s![..1000]), rt23(s![..1000].into()));
assert_same_result(nds1(s![999..1000]), rt23(s![999..1000].into()));
assert_same_result(nds1(s![-1000..]), rt23(s![-1000..].into()));
assert_same_result(nds1(s![..-1000]), rt23(s![..-1000].into()));
#[allow(clippy::reversed_empty_ranges)]
assert_same_result(nds1(s![-999..-1000]), rt23(s![-999..-1000].into()));
#[allow(clippy::reversed_empty_ranges)]
assert_same_result(nds1(s![3..0]), rt23(s![3..0].into()));
#[allow(clippy::reversed_empty_ranges)]
assert_same_result(nds1(s![-1..-2]), rt23(s![-1..-2].into()));
assert_same_result(nds1(s![..-3]), rt23(s![..-3].into()));
assert_same_result(nds1(s![..=-3]), rt23(s![..=-3].into()));
assert_same_result(nds1(s![-1..]), rt23(s![-1..].into()));
assert_same_result(nds1(s![-3..-1]), rt23(s![-3..-1].into()));
assert_same_result(nds1(s![-3..=-1]), rt23(s![-3..=-1].into()));
assert_same_result(nds1(s![-3..=-1]), rt23(s![-3..=-1].into()));
assert_same_result(nds1(s![-2..=-2]), rt23(s![-2..=-2].into()));
#[allow(clippy::reversed_empty_ranges)]
assert_same_result(nds1(s![1..-1]), rt23(s![1..-1].into()));
assert_same_result(nds1(s![..]), rt23((s![..]).into()));
assert_same_result(nds1(s![..3]), rt23((s![..3]).into()));
assert_same_result(nds1(s![..=3]), rt23((s![..=3]).into()));
assert_same_result(nds1(s![1..]), rt23((s![1..]).into()));
assert_same_result(nds1(s![1..3]), rt23((s![1..3]).into()));
assert_same_result(nds1(s![1..=3]), rt23((s![1..=3]).into()));
assert_same_result(nds1(s![2..=2]), rt23(s![2..=2].into()));
Ok(())
}
#[test]
fn counts_and_files() -> Result<(), Box<BedErrorPlus>> {
let file_name = sample_bed_file("small.bed")?;
let mut bed = Bed::builder(&file_name)
.iid(["i1", "i2", "i3", "i4"])
.build()?;
let iid_count = bed.iid_count()?;
assert_eq!(iid_count, 4);
let fid_result = bed.fid();
assert_error_variant!(
fid_result,
BedErrorPlus::BedError(BedError::InconsistentCount(_, _, _))
);
assert_error_variant!(
Bed::builder(&file_name)
.fid(["f1", "f1", "f1"])
.iid(["i1", "i2", "i3", "i4"])
.build(),
BedErrorPlus::BedError(BedError::InconsistentCount(_, _, _))
);
let mut bed = Bed::builder(&file_name)
.bim_path(sample_file("small.bad_bim")?)
.build()?;
assert_error_variant!(
bed.sid(),
BedErrorPlus::BedError(BedError::MetadataFieldCount(_, _, _))
);
let mut bed = Bed::builder(&file_name).iid_count(4).build()?;
assert_eq!(bed.iid_count()?, 4);
assert_error_variant!(
bed.iid(),
BedErrorPlus::BedError(BedError::InconsistentCount(_, _, _))
);
let mut bed = Bed::builder(&file_name)
.bim_path(sample_file("small.bim")?)
.build()?;
assert_eq!(bed.iid_count()?, 3);
assert_eq!(bed.sid_count()?, 4);
let mut bed = Bed::new(&file_name)?;
assert_eq!(bed.iid_count()?, 3);
assert_eq!(bed.sid_count()?, 4);
let mut bed = Bed::builder(&file_name).build()?;
let _ = bed.iid()?;
let _ = bed.iid_count()?;
Ok(())
}
#[test]
fn bool_read() -> Result<(), Box<BedErrorPlus>> {
let file_name = sample_bed_file("small.bed")?;
let mut bed = Bed::new(file_name)?;
let result = ReadOptions::builder()
.iid_index([false, false, true, false])
.i8()
.read(&mut bed);
println!("{result:?}");
assert_error_variant!(
result,
BedErrorPlus::BedError(BedError::BoolArrayVectorWrongLength(_, _))
);
let _val = ReadOptions::builder()
.iid_index([false, false, true])
.i8()
.read(&mut bed)?;
Ok(())
}
#[test]
fn i8_etc() -> Result<(), Box<BedErrorPlus>> {
let file_name = sample_bed_file("small.bed")?;
let mut bed = Bed::new(file_name)?;
let _val = ReadOptions::builder()
.f()
.i8()
.iid_index([false, false, true])
.read(&mut bed)?;
Ok(())
}
#[test]
fn fill() -> Result<(), Box<BedErrorPlus>> {
let file_name = sample_bed_file("small.bed")?;
let mut bed = Bed::new(file_name)?;
let read_options = ReadOptions::builder()
.f()
.i8()
.iid_index([false, false, true])
.build()?;
let mut val = nd::Array2::<i8>::default((3, 4));
let result = bed.read_and_fill_with_options(&mut val.view_mut(), &read_options);
assert_error_variant!(
result,
BedErrorPlus::BedError(BedError::InvalidShape(_, _, _, _))
);
let mut val = nd::Array2::<i8>::default((1, 4));
bed.read_and_fill_with_options(&mut val.view_mut(), &read_options)?;
assert_eq!(bed.dim()?, (3, 4));
Ok(())
}
#[test]
fn read_options_builder() -> Result<(), Box<BedErrorPlus>> {
let file_name = sample_bed_file("small.bed")?;
let mut bed = Bed::new(file_name)?;
let val = ReadOptions::builder().sid_index(2).f64().read(&mut bed)?;
assert_eq_nan(&val, &nd::array![[f64::NAN], [f64::NAN], [2.0]]);
let val = ReadOptions::builder()
.sid_index([2, 3, 0])
.f64()
.read(&mut bed)?;
assert_eq_nan(
&val,
&nd::array![[f64::NAN, 0.0, 1.0], [f64::NAN, 2.0, 2.0], [2.0, 0.0, 0.0]],
);
let val = ReadOptions::builder()
.sid_index(1..4)
.f64()
.read(&mut bed)?;
assert_eq_nan(
&val,
&nd::array![[0.0, f64::NAN, 0.0], [0.0, f64::NAN, 2.0], [1.0, 2.0, 0.0]],
);
use std::collections::HashSet;
println!("{:?}", bed.chromosome()?.iter().collect::<HashSet<_>>());
let val = ReadOptions::builder()
.sid_index(bed.chromosome()?.map(|elem| elem == "5"))
.f64()
.read(&mut bed)?;
assert_eq_nan(&val, &nd::array![[f64::NAN], [f64::NAN], [2.0]]);
let val = ReadOptions::builder().iid_index(0).f64().read(&mut bed)?;
assert_eq_nan(&val, &nd::array![[1.0, 0.0, f64::NAN, 0.0]]);
use ndarray::s;
let val = ReadOptions::builder()
.iid_index(s![..;2])
.f64()
.read(&mut bed)?;
assert_eq_nan(
&val,
&nd::array![[1.0, 0.0, f64::NAN, 0.0], [0.0, 1.0, 2.0, 0.0]],
);
let val = ReadOptions::builder()
.iid_index([-1, -2])
.sid_index(-1)
.f64()
.read(&mut bed)?;
println!("{:?}", &val);
assert_eq_nan(&val, &nd::array![[0.0], [2.0]]);
Ok(())
}
#[test]
fn bed_builder() -> Result<(), Box<BedErrorPlus>> {
let file_name = sample_bed_file("small.bed")?;
let mut bed = Bed::builder(&file_name).build()?;
println!("{:?}", bed.iid()?);
println!("{:?}", bed.sid()?);
let val = bed.read::<f64>()?;
assert_eq_nan(
&val,
&nd::array![
[1.0, 0.0, f64::NAN, 0.0],
[2.0, 0.0, f64::NAN, 2.0],
[0.0, 1.0, 2.0, 0.0]
],
);
let mut bed = Bed::builder(&file_name).build()?;
let val = ReadOptions::builder().sid_index(2).f64().read(&mut bed)?;
assert_eq_nan(&val, &nd::array![[f64::NAN], [f64::NAN], [2.0]]);
let mut bed = Bed::builder(&file_name)
.iid(["sample1", "sample2", "sample3"])
.build()?;
println!("{:?}", bed.iid()?); println!("{:?}", bed.sid()?);
let mut bed = Bed::builder(&file_name).iid_count(3).sid_count(4).build()?;
let val = bed.read::<f64>()?;
assert_eq_nan(
&val,
&nd::array![
[1.0, 0.0, f64::NAN, 0.0],
[2.0, 0.0, f64::NAN, 2.0],
[0.0, 1.0, 2.0, 0.0]
],
);
let mut bed = Bed::builder(&file_name)
.skip_father()
.skip_mother()
.skip_sex()
.skip_pheno()
.skip_allele_1()
.skip_allele_2()
.build()?;
println!("{:?}", bed.iid()?);
bed.allele_2().expect_err("Can't be read");
Ok::<(), Box<BedErrorPlus>>(())
}
#[test]
#[allow(clippy::needless_borrows_for_generic_args)]
fn negative_indexing() -> Result<(), Box<BedErrorPlus>> {
let file_name = sample_bed_file("small.bed")?;
let mut bed = Bed::new(&file_name)?;
for index in [-4, 3] {
match ReadOptions::builder().iid_index(index).i8().read(&mut bed) {
Err(ref boxed_error) => match **boxed_error {
BedErrorPlus::BedError(BedError::IidIndexTooBig(x)) => {
assert_eq!(x, index);
}
_ => panic!("test failure"),
},
_ => panic!("test failure"),
}
}
for index in [-3, 0] {
let val = ReadOptions::builder()
.iid_index(index)
.i8()
.read(&mut bed)?;
assert!(val[[0, 0]] == 1,);
}
for index in [-1, 2] {
let val = ReadOptions::builder()
.iid_index(index)
.i8()
.read(&mut bed)?;
assert!(val[[0, 0]] == 0,);
}
for index in [-5, 4] {
match ReadOptions::builder().sid_index(index).i8().read(&mut bed) {
Err(ref boxed_error) => match **boxed_error {
BedErrorPlus::BedError(BedError::SidIndexTooBig(x)) => {
assert_eq!(x, index);
}
_ => panic!("test failure"),
},
_ => panic!("test failure"),
}
}
for index in [-4, 0] {
let val = ReadOptions::builder()
.sid_index(index)
.i8()
.read(&mut bed)?;
assert!(val[[0, 0]] == 1,);
}
for index in [-1, 3] {
let val = ReadOptions::builder()
.sid_index(index)
.i8()
.read(&mut bed)?;
assert!(val[[0, 0]] == 0,);
}
Ok(())
}
#[test]
fn index_doc() -> Result<(), Box<BedErrorPlus>> {
let file_name = sample_bed_file("some_missing.bed")?;
let mut bed = Bed::new(file_name)?;
println!("{:?}", bed.dim()?);
let val = ReadOptions::builder().f64().read(&mut bed)?;
assert!(val.dim() == (100, 100));
let val = ReadOptions::builder().iid_index(10).f64().read(&mut bed)?;
assert!(val.dim() == (1, 100));
let val = ReadOptions::builder()
.iid_index(vec![0, 5, -1])
.sid_index(3)
.f64()
.read(&mut bed)?;
assert!(val.dim() == (3, 1));
let val = ReadOptions::builder()
.iid_index(nd::array![0, 5, -1])
.sid_index(3)
.f64()
.read(&mut bed)?;
assert!(val.dim() == (3, 1));
let val = ReadOptions::builder()
.iid_index([0, 5, -1])
.sid_index(3)
.f64()
.read(&mut bed)?;
assert!(val.dim() == (3, 1));
let chrom_5 = bed.chromosome()?.map(|elem| elem == "5");
let val = ReadOptions::builder()
.sid_index(chrom_5)
.f64()
.read(&mut bed)?;
assert!(val.dim() == (100, 6));
let val = ReadOptions::builder()
.iid_index(s![..;2])
.sid_index(s![..;3])
.f64()
.read(&mut bed)?;
assert!(val.dim() == (50, 34));
let val = ReadOptions::builder()
.iid_index(s![-10..;-1])
.sid_index(s![..;-3])
.f64()
.read(&mut bed)?;
assert!(val.dim() == (10, 34));
Ok(())
}
#[test]
fn index_options() -> Result<(), Box<BedErrorPlus>> {
let mut bed = Bed::new(sample_bed_file("some_missing.bed")?)?;
#[allow(clippy::let_unit_value)]
let index: () = ();
let all = ReadOptions::builder()
.iid_index(index)
.sid_index(index)
.f64()
.read(&mut bed)?;
assert!(all.dim() == (100, 100));
let mut index: [bool; 100] = [false; 100];
index[0] = true;
index[2] = true;
let val = ReadOptions::builder()
.iid_index(index)
.sid_index(index)
.f64()
.read(&mut bed)?;
let expected = all
.select(nd::Axis(0), [0, 2].as_slice())
.select(nd::Axis(1), [0, 2].as_slice());
assert!(
allclose(&val.view(), &expected.view(), 1e-08, true),
"not close"
);
let mut index: nd::Array1<bool> = nd::Array::from_elem(100, false);
index[0] = true;
index[2] = true;
let val = ReadOptions::builder()
.iid_index(&index)
.sid_index(index)
.f64()
.read(&mut bed)?;
let expected = all
.select(nd::Axis(0), [0, 2].as_slice())
.select(nd::Axis(1), [0, 2].as_slice());
assert!(
allclose(&val.view(), &expected.view(), 1e-08, true),
"not close"
);
let mut index: Vec<bool> = vec![false; 100];
index[0] = true;
index[2] = true;
let val = ReadOptions::builder()
.iid_index(&index)
.sid_index(index)
.f64()
.read(&mut bed)?;
let expected = all
.select(nd::Axis(0), [0, 2].as_slice())
.select(nd::Axis(1), [0, 2].as_slice());
assert!(
allclose(&val.view(), &expected.view(), 1e-08, true),
"not close"
);
let index: isize = 2;
let val = ReadOptions::builder()
.iid_index(index)
.sid_index(index)
.f64()
.read(&mut bed)?;
let expected = all.slice(s![2isize..=2, 2isize..=2]);
assert!(
allclose(&val.view(), &expected.view(), 1e-08, true),
"not close"
);
let index: isize = -1;
let val = ReadOptions::builder()
.iid_index(index)
.sid_index(index)
.f64()
.read(&mut bed)?;
let expected = all.slice(s![99isize..=99, 99isize..=99]);
assert!(
allclose(&val.view(), &expected.view(), 1e-08, true),
"not close"
);
let index: Vec<isize> = vec![0, 10, -2];
let val = ReadOptions::builder()
.iid_index(&index)
.sid_index(&index)
.f64()
.read(&mut bed)?;
let expected_index = vec![0, 10, 98usize];
let expected = all
.select(nd::Axis(0), expected_index.as_slice())
.select(nd::Axis(1), expected_index.as_slice());
assert!(
allclose(&val.view(), &expected.view(), 1e-08, true),
"not close"
);
let index: &[isize] = &[0, 10, -2];
let val = ReadOptions::builder()
.iid_index(index)
.sid_index(index)
.f64()
.read(&mut bed)?;
let expected_index = vec![0, 10, 98usize];
let expected = all
.select(nd::Axis(0), expected_index.as_slice())
.select(nd::Axis(1), expected_index.as_slice());
assert!(
allclose(&val.view(), &expected.view(), 1e-08, true),
"not close"
);
let val = ReadOptions::builder()
.iid_index([0, 10, -2])
.sid_index([0, 10, -2])
.f64()
.read(&mut bed)?;
let expected_index = vec![0, 10, 98usize];
let expected = all
.select(nd::Axis(0), expected_index.as_slice())
.select(nd::Axis(1), expected_index.as_slice());
assert!(
allclose(&val.view(), &expected.view(), 1e-08, true),
"not close"
);
let index: nd::Array1<isize> = nd::array![0, 10, -2];
let val = ReadOptions::builder()
.iid_index(&index)
.sid_index(index)
.f64()
.read(&mut bed)?;
let expected_index = vec![0, 10, 98usize];
let expected = all
.select(nd::Axis(0), expected_index.as_slice())
.select(nd::Axis(1), expected_index.as_slice());
assert!(
allclose(&val.view(), &expected.view(), 1e-08, true),
"not close"
);
let index: std::ops::Range<usize> = 10..20;
let val = ReadOptions::builder()
.iid_index(&index)
.sid_index(index)
.f64()
.read(&mut bed)?;
let expected = all.slice(s![10usize..20, 10usize..20]);
assert!(
allclose(&val.view(), &expected.view(), 1e-08, true),
"not close"
);
let index: std::ops::RangeFrom<usize> = 50..;
let val = ReadOptions::builder()
.iid_index(&index)
.sid_index(index)
.f64()
.read(&mut bed)?;
let expected = all.slice(s![50usize.., 50usize..]);
assert!(
allclose(&val.view(), &expected.view(), 1e-08, true),
"not close"
);
let index: std::ops::RangeFull = ..;
let val = ReadOptions::builder()
.iid_index(index)
.sid_index(index)
.f64()
.read(&mut bed)?;
let expected = all.slice(s![.., ..]);
assert!(
allclose(&val.view(), &expected.view(), 1e-08, true),
"not close"
);
let index: std::ops::RangeTo<usize> = ..3;
let val = ReadOptions::builder()
.iid_index(index)
.sid_index(index)
.f64()
.read(&mut bed)?;
let expected = all.slice(s![..3, ..3]);
assert!(
allclose(&val.view(), &expected.view(), 1e-08, true),
"not close"
);
let index: std::ops::RangeToInclusive<usize> = ..=19;
let val = ReadOptions::builder()
.iid_index(index)
.sid_index(index)
.f64()
.read(&mut bed)?;
let expected = all.slice(s![..=19, ..=19]);
assert!(
allclose(&val.view(), &expected.view(), 1e-08, true),
"not close"
);
let index: std::ops::RangeInclusive<usize> = 1..=3;
let val = ReadOptions::builder()
.iid_index(&index)
.sid_index(index)
.f64()
.read(&mut bed)?;
let expected = all.slice(s![1..=3, 1..=3]);
assert!(
allclose(&val.view(), &expected.view(), 1e-08, true),
"not close"
);
let index: SliceInfo1 = s![-20..-10;-2];
let val = ReadOptions::builder()
.iid_index(index)
.sid_index(index)
.f64()
.read(&mut bed)?;
let expected = all.slice(s![-20..-10;-2,-20..-10;-2]);
assert!(
allclose(&val.view(), &expected.view(), 1e-08, true),
"not close"
);
Ok(())
}
#[test]
fn set_metadata() -> Result<(), Box<BedErrorPlus>> {
let file_name = sample_bed_file("small.bed")?;
let metadata = Metadata::builder()
.iid(["iid1", "iid2", "iid3"])
.sid(["sid1", "sid2", "sid3", "sid4"])
.build()?;
let mut bed = Bed::builder(&file_name).metadata(&metadata).build()?;
let metadata2 = bed.metadata()?;
println!("{metadata2:?}");
let mut bed = Bed::new(&file_name)?;
let metadata = bed.metadata()?;
println!("{metadata:?}");
let mut bed = Bed::builder(&file_name).metadata(&metadata).build()?;
let metadata2 = bed.metadata()?;
println!("{metadata2:?}");
Ok(())
}
#[test]
fn metadata_print() -> Result<(), Box<BedErrorPlus>> {
let file_name = sample_bed_file("small.bed")?;
let mut bed = Bed::new(file_name)?;
let fid = bed.fid()?;
println!("{fid:?}"); let iid = bed.iid()?;
println!("{iid:?}"); let father = bed.father()?;
println!("{father:?}"); let mother = bed.mother()?;
println!("{mother:?}"); let sex = bed.sex()?;
println!("{sex:?}"); let pheno = bed.pheno()?;
println!("{pheno:?}");
let chromosome = bed.chromosome()?;
println!("{chromosome:?}"); let sid = bed.sid()?;
println!("{sid:?}"); let cm_position = bed.cm_position()?;
println!("{cm_position:?}"); let bp_position = bed.bp_position()?;
println!("{bp_position:?}"); let allele_1 = bed.allele_1()?;
println!("{allele_1:?}"); let allele_2 = bed.allele_2()?;
println!("{allele_2:?}"); Ok(())
}
#[test]
fn iid_index() -> Result<(), Box<BedErrorPlus>> {
let file_name = sample_bed_file("some_missing.bed")?;
let mut bed = Bed::new(file_name)?;
let val = ReadOptions::builder().iid_index(3).f64().read(&mut bed)?;
assert!(val.dim() == (1, 100));
let val = ReadOptions::builder()
.iid_index([0, 5, -1])
.f64()
.read(&mut bed)?;
assert!(val.dim() == (3, 100));
let val = ReadOptions::builder()
.iid_index(20..30)
.f64()
.read(&mut bed)?;
assert!(val.dim() == (10, 100));
let val = ReadOptions::builder()
.iid_index(s![..;2])
.f64()
.read(&mut bed)?;
assert!(val.dim() == (50, 100));
let female = bed.sex()?.map(|elem| *elem == 2);
let chrom_5 = bed.chromosome()?.map(|elem| elem == "5");
let val = ReadOptions::builder()
.iid_index(female)
.sid_index(chrom_5)
.f64()
.read(&mut bed)?;
println!("{:?}", val.dim());
assert_eq!(val.dim(), (50, 6));
Ok(())
}
#[test]
fn write_options_metadata() -> Result<(), Box<BedErrorPlus>> {
let output_folder = TempDir::default();
let output_file = output_folder.join("small.bed");
let write_options_result = WriteOptions::<f32>::builder(&output_file).build(0, 0);
println!("{write_options_result:?}"); write_options_result?;
let write_options_result = WriteOptions::<f32>::builder(&output_file)
.iid(["iid1", "iid2", "iid3"])
.build(3, 4);
println!("{write_options_result:?}"); let iid_count = write_options_result?.iid_count();
assert_eq!(iid_count, 3);
let write_options_result = WriteOptions::<f32>::builder(&output_file)
.chromosome(["1", "1", "1"])
.sid(["sid1", "sid2", "sid3", "sid4"])
.build(3, 4);
println!("{write_options_result:?}"); assert_error_variant!(
write_options_result,
BedErrorPlus::BedError(BedError::InconsistentCount(_, _, _))
);
let val = nd::array![
[1.0, 0.0, f64::NAN, 0.0],
[2.0, 0.0, f64::NAN, 2.0],
[0.0, 1.0, 2.0, 0.0]
];
WriteOptions::builder(&output_file).write(&val)?;
assert_eq!(3, Bed::new(&output_file)?.iid_count()?);
let write_options = WriteOptions::<f64>::builder(&output_file).build(3, 4)?;
Bed::write_with_options(&val, &write_options)?;
let sid_count = write_options.sid_count();
println!("{sid_count:?}");
assert_eq!(4, sid_count);
let val2 = nd::array![[1.0, 0.0, f64::NAN, 0.0], [0.0, 1.0, 2.0, 0.0]];
let write_options = WriteOptions::<f64>::builder(&output_file).build(3, 4)?;
Bed::write_with_options(&val, &write_options)?;
let result = Bed::write_with_options(&val2, &write_options);
assert_error_variant!(
result,
BedErrorPlus::BedError(BedError::InconsistentCount(_, _, _))
);
let write_options_result = WriteOptions::<f32>::builder(&output_file).build(3, 4);
println!("{write_options_result:?}"); let sid_count = write_options_result?.sid_count();
assert_eq!(sid_count, 4);
let write_options_result = WriteOptions::<f32>::builder(&output_file)
.iid(["iid1", "iid2", "iid3"])
.build(4, 4);
assert_error_variant!(
write_options_result,
BedErrorPlus::BedError(BedError::InconsistentCount(_, _, _))
);
let result = WriteOptions::builder(&output_file)
.iid(["iid1", "iid2", "iid3", "iid4"])
.write(&val);
assert_error_variant!(
result,
BedErrorPlus::BedError(BedError::InconsistentCount(_, _, _))
);
let write_options = WriteOptions::builder(&output_file)
.iid(["iid1", "iid2", "iid3", "iid4"])
.build(4, 4)?;
let result = Bed::write_with_options(&val, &write_options);
assert_error_variant!(
result,
BedErrorPlus::BedError(BedError::InconsistentCount(_, _, _))
);
let write_options = WriteOptions::builder(&output_file).build(4, 4)?;
let result = Bed::write_with_options(&val, &write_options);
assert_error_variant!(
result,
BedErrorPlus::BedError(BedError::InconsistentCount(_, _, _))
);
WriteOptions::builder(&output_file)
.sid(["sid1", "sid2", "sid3", "sid4"])
.write(&val)?;
let write_options = WriteOptions::builder(&output_file)
.sid(["sid1", "sid2", "sid3", "sid4"])
.build(3, 4)?;
Bed::write_with_options(&val, &write_options)?;
let write_options = WriteOptions::builder(output_file)
.fid(["fid1", "fid1", "fid2"])
.iid(["iid1", "iid2", "iid3"])
.father(["iid23", "iid23", "iid22"])
.mother(["iid34", "iid34", "iid33"])
.sex([1, 2, 0])
.pheno(["red", "red", "blue"])
.chromosome(["1", "1", "5", "Y"])
.sid(["sid1", "sid2", "sid3", "sid4"])
.cm_position([100.4, 2000.5, 4000.7, 7000.9])
.bp_position([1, 100, 1000, 1004])
.f32()
.build(3, 4)?;
let metadata = write_options.metadata();
println!("{metadata:?}");
Ok(())
}
#[test]
fn metadata_use() -> Result<(), Box<BedErrorPlus>> {
let mut bed = Bed::new(sample_bed_file("small.bed")?)?;
let metadata = bed.metadata()?;
let shape = bed.dim()?;
let mut rng = StdRng::seed_from_u64(0);
let val = nd::Array::random_using(shape, Uniform::from(-1..3), &mut rng);
let temp_out = TempDir::default();
let output_file = temp_out.join("random.bed");
WriteOptions::builder(output_file)
.metadata(&metadata)
.missing_value(-1)
.write(&val)?;
Ok(())
}
#[test]
fn metadata_same() -> Result<(), Box<BedErrorPlus>> {
let iid_count = 1_000;
let sid_count = 5_000;
let file_count = 10;
let metadata = Metadata::builder()
.iid((0..iid_count).map(|iid_index| format!("iid_{iid_index}")))
.sid((0..sid_count).map(|sid_index| format!("sid_{sid_index}")))
.build()?;
let temp_out = TempDir::default();
for file_index in 0..file_count {
let output_file = temp_out.join(format!("random{file_index}.bed"));
let mut rng = StdRng::seed_from_u64(0);
let val = nd::Array::random_using((iid_count, sid_count), Uniform::from(-1..3), &mut rng);
WriteOptions::builder(output_file)
.metadata(&metadata)
.missing_value(-1)
.write(&val)?;
}
Ok(())
}
#[test]
fn struct_play() -> Result<(), Box<BedErrorPlus>> {
let metadata = Metadata::builder().build()?.fill(100, 100)?;
println!("{0:?}", metadata.iid());
Ok(())
}
#[test]
fn metadata_bed() -> Result<(), Box<BedErrorPlus>> {
let file_name = sample_bed_file("small.bed")?;
let mut bed = Bed::new(file_name)?;
let metadata = bed.metadata()?;
println!("{0:?}", metadata.iid()); println!("{0:?}", metadata.sid()); Ok(())
}
fn rt1<R>(range_thing: R) -> Result<Result<nd::Array2<i8>, Box<BedErrorPlus>>, Box<BedErrorPlus>>
where
R: std::ops::RangeBounds<usize>
+ std::fmt::Debug
+ Clone
+ std::slice::SliceIndex<[isize], Output = [isize]>
+ std::panic::RefUnwindSafe,
{
println!("Running {:?}", &range_thing);
let file_name = sample_bed_file("toydata.5chrom.bed")?;
let result1 = catch_unwind(|| {
let mut bed = Bed::new(&file_name).unwrap();
let all: Vec<isize> = (0..(bed.iid_count().unwrap() as isize)).collect();
let mut bed = Bed::new(&file_name).unwrap();
let iid_index: &[isize] = &all[range_thing.clone()];
ReadOptions::builder()
.iid_index(iid_index)
.i8()
.read(&mut bed)
});
match result1 {
Err(_) => Err(BedError::PanickedThread().into()),
Ok(bed_result) => Ok(bed_result),
}
}
fn rt2(
range_thing: bed_reader::Index,
) -> Result<Result<nd::Array2<i8>, Box<BedErrorPlus>>, Box<BedErrorPlus>> {
println!("Running {:?}", &range_thing);
let file_name = sample_bed_file("toydata.5chrom.bed")?;
let result2 = catch_unwind(|| {
let mut bed = Bed::new(file_name).unwrap();
ReadOptions::builder()
.iid_index(range_thing)
.i8()
.read(&mut bed)
});
match result2 {
Err(_) => Err(BedError::PanickedThread().into()),
Ok(bed_result) => Ok(bed_result),
}
}
fn rt23(range_thing: bed_reader::Index) -> (RrArray2, RrUsize) {
(rt2(range_thing.clone()), rt3(range_thing))
}
fn rt3(
range_thing: bed_reader::Index,
) -> Result<Result<usize, Box<BedErrorPlus>>, Box<BedErrorPlus>> {
println!("Running {:?}", &range_thing);
let file_name = sample_bed_file("toydata.5chrom.bed").unwrap();
let result3 = catch_unwind(|| {
let mut bed = Bed::new(file_name).unwrap();
range_thing.len(bed.iid_count().unwrap()).unwrap()
});
match result3 {
Err(_) => Err(BedError::PanickedThread().into()),
Ok(bed_result) => Ok(Ok(bed_result)),
}
}
fn nds1(
range_thing: SliceInfo1,
) -> Result<Result<nd::Array2<i8>, Box<BedErrorPlus>>, Box<BedErrorPlus>> {
println!("Running {:?}", &range_thing);
let file_name = sample_bed_file("toydata.5chrom.bed")?;
let result1 = catch_unwind(|| {
let mut bed = Bed::new(&file_name).unwrap();
let all: nd::Array1<isize> = (0..(bed.iid_count().unwrap() as isize)).collect();
let mut bed = Bed::new(&file_name).unwrap();
let iid_index = &all.slice(&range_thing);
ReadOptions::builder()
.iid_index(iid_index)
.i8()
.read(&mut bed)
});
match result1 {
Err(_) => Err(BedError::PanickedThread().into()),
Ok(bed_result) => Ok(bed_result),
}
}
type RrArray2 = Result<Result<nd::Array2<i8>, Box<BedErrorPlus>>, Box<BedErrorPlus>>;
type RrUsize = Result<Result<usize, Box<BedErrorPlus>>, Box<BedErrorPlus>>;
fn assert_same_result(result1: RrArray2, result23: (RrArray2, RrUsize)) {
let result2 = result23.0;
let result3 = result23.1;
let err1 = is_err2(&result1);
let err2 = is_err2(&result2);
let err3 = is_err2(&result3);
if err1 || err2 || err3 {
if !err1 || !err2 || !err3 {
println!("{result1:?}");
println!("{result2:?}");
println!("{result3:?}");
panic!("all should panic/error the same");
}
return;
}
let result1 = result1.unwrap().unwrap();
let result2 = result2.unwrap().unwrap();
let result3 = result3.unwrap().unwrap();
println!("{result1:?}");
println!("{result2:?}");
println!("{result3:?}");
assert!(
allclose(&result1.view(), &result2.view(), 0, true),
"not close"
);
assert!(result1.dim().0 == result3, "not same length");
}
fn is_err2<T>(result_result: &Result<Result<T, Box<BedErrorPlus>>, Box<BedErrorPlus>>) -> bool {
!matches!(result_result, Ok(Ok(_)))
}
#[test]
fn read_and_fill_with_options() -> Result<(), Box<BedErrorPlus>> {
use bed_reader::assert_eq_nan;
use bed_reader::{Bed, ReadOptions};
use ndarray as nd;
let file_name = sample_bed_file("small.bed")?;
let mut bed = Bed::new(file_name)?;
let read_options = ReadOptions::builder().sid_index(2).build()?;
let mut val = nd::Array2::<f64>::default((3, 1));
bed.read_and_fill_with_options(&mut val.view_mut(), &read_options)?;
assert_eq_nan(&val, &nd::array![[f64::NAN], [f64::NAN], [2.0]]);
let file_name = sample_bed_file("small.bed")?;
let mut bed = Bed::new(file_name)?;
let mut val = nd::Array2::<f64>::default((3, 1));
ReadOptions::builder()
.sid_index(2)
.read_and_fill(&mut bed, &mut val.view_mut())?;
assert_eq_nan(&val, &nd::array![[f64::NAN], [f64::NAN], [2.0]]);
Ok(())
}
#[test]
fn bed_builder_metadata() -> Result<(), Box<BedErrorPlus>> {
let file_name = sample_bed_file("small.bed")?;
let metadata = Metadata::builder()
.iid(["i1", "i2", "i3"])
.sid(["s1", "s2", "s3", "s4"])
.build()?;
let result = Bed::builder(&file_name)
.fid(["f1", "f2", "f3", "f4"])
.metadata(&metadata)
.build();
assert_error_variant!(
result,
BedErrorPlus::BedError(BedError::InconsistentCount(_, _, _))
);
let metadata = Metadata::builder()
.iid(["i1", "i2", "i3"])
.sid(["s1", "s2", "s3", "s4"])
.build()?;
let mut bed = Bed::builder(&file_name)
.fid(["f1", "f2", "f3"])
.iid(["x1", "x2", "x3"])
.metadata(&metadata)
.build()?;
println!("{0:?}", bed.fid()?); println!("{0:?}", bed.iid()?); println!("{0:?}", bed.sid()?); println!("{0:?}", bed.chromosome()?);
let mut bed = Bed::builder(file_name)
.skip_fid()
.fid(["f1", "f2", "f3"])
.iid(["x1", "x2", "x3"])
.metadata(&metadata)
.build()?;
bed.fid().expect_err("Should fail");
println!("{0:?}", bed.iid()?); println!("{0:?}", bed.sid()?); println!("{0:?}", bed.chromosome()?);
Ok(())
}
#[test]
fn write_options_builder_metadata() -> Result<(), Box<BedErrorPlus>> {
let output_folder = TempDir::default();
let output_file = output_folder.join("small_m.bed");
let metadata = Metadata::builder()
.iid(["i1", "i2", "i3"])
.sid(["s1", "s2", "s3", "s4"])
.build()?;
let write_options = WriteOptions::builder(output_file)
.f32()
.fid(["f1", "f2", "f3"])
.iid(["x1", "x2", "x3"])
.metadata(&metadata)
.build(3, 4)?;
println!("{0:?}", write_options.fid()); println!("{0:?}", write_options.iid()); println!("{0:?}", write_options.sid()); println!("{0:?}", write_options.chromosome()); Ok(())
}
#[test]
fn metadata_builder_metadata() -> Result<(), Box<BedErrorPlus>> {
let metadata1 = Metadata::builder()
.iid(["i1", "i2", "i3"])
.sid(["s1", "s2", "s3", "s4"])
.build()?;
let metadata2 = Metadata::builder()
.fid(["f1", "f2", "f3"])
.iid(["x1", "x2", "x3"])
.metadata(&metadata1)
.build()?;
println!("{0:?}", metadata2.fid()); println!("{0:?}", metadata2.iid()); println!("{0:?}", metadata2.sid()); println!("{0:?}", metadata2.chromosome());
Ok(())
}
#[test]
fn metadata_builder() -> Result<(), Box<BedErrorPlus>> {
let metadata = Metadata::builder()
.iid(["i1", "i2", "i3"])
.sid(["s1", "s2", "s3", "s4"])
.build()?;
let mut rng = StdRng::seed_from_u64(0);
let val = nd::Array::random_using((3, 4), Uniform::from(-1..3), &mut rng);
let temp_out = TempDir::default();
let output_file = temp_out.join("random.bed");
WriteOptions::builder(output_file)
.metadata(&metadata)
.missing_value(-1)
.write(&val)?;
Ok(())
}
#[test]
fn metadata_read_fam_bim() -> Result<(), Box<BedErrorPlus>> {
let skip_set = HashSet::<MetadataFields>::new();
let metadata_empty = Metadata::new();
let (metadata_fam, iid_count) =
metadata_empty.read_fam(sample_file("small.fam")?, &skip_set)?;
let (metadata_bim, sid_count) = metadata_fam.read_bim(sample_file("small.bim")?, &skip_set)?;
assert_eq!(iid_count, 3);
assert_eq!(sid_count, 4);
println!("{0:?}", metadata_bim.iid()); println!("{0:?}", metadata_bim.sid()); println!("{0:?}", metadata_bim.chromosome());
Ok(())
}
#[test]
fn metadata_fill() -> Result<(), Box<BedErrorPlus>> {
let metadata0 = Metadata::builder()
.iid(["i1", "i2", "i3"])
.sid(["s1", "s2", "s3", "s4"])
.build()?;
let metadata_filled = metadata0.fill(3, 4)?;
println!("{0:?}", metadata_filled.iid()); println!("{0:?}", metadata_filled.sid()); println!("{0:?}", metadata_filled.chromosome());
Ok(())
}
#[test]
fn metadata_fam_bim_write() -> Result<(), Box<BedErrorPlus>> {
let metadata0 = Metadata::builder()
.iid(["i1", "i2", "i3"])
.sid(["s1", "s2", "s3", "s4"])
.build()?;
let metadata_filled = metadata0.fill(3, 4)?;
let temp_out = TempDir::default();
let output_file = temp_out.join("no_bed.fam");
metadata_filled.write_fam(output_file)?;
let temp_out = TempDir::default();
let output_file = temp_out.join("no_bed.bim");
metadata_filled.write_bim(output_file)?;
Ok(())
}
#[test]
fn metadata_iid_sid() -> Result<(), Box<BedErrorPlus>> {
let metadata = Metadata::builder().iid(["i1", "i2", "i3"]).build()?;
println!("{0:?}", metadata.iid()); println!("{0:?}", metadata.sid()); Ok(())
}
#[test]
fn read_options_properties() -> Result<(), Box<BedErrorPlus>> {
let read_options = ReadOptions::builder().sid_index([2, 3, 0]).i8().build()?;
assert_eq!(read_options.missing_value(), -127);
println!("{0:?}", read_options.iid_index()); println!("{0:?}", read_options.sid_index()); assert!(read_options.is_f());
assert!(read_options.is_a1_counted());
assert_eq!(read_options.num_threads(), None);
let file_name = sample_bed_file("small.bed")?;
let mut bed = Bed::new(file_name)?;
let val = bed.read_with_options(&read_options)?;
assert_eq_nan(&val, &nd::array![[-127, 0, 1], [-127, 2, 2], [2, 0, 0]]);
Ok(())
}
#[test]
fn write_options_properties() -> Result<(), Box<BedErrorPlus>> {
let output_folder = TempDir::default();
let output_file = output_folder.join("small.bed");
let write_options = WriteOptions::builder(output_file)
.f64()
.iid(["i1", "i2", "i3"])
.sid(["s1", "s2", "s3", "s4"])
.build(3, 4)?;
println!("{0:?}", write_options.path()); println!("{0:?}", write_options.fam_path()); println!("{0:?}", write_options.bim_path());
println!("{0:?}", write_options.fid()); println!("{0:?}", write_options.iid()); println!("{0:?}", write_options.father()); println!("{0:?}", write_options.mother()); println!("{0:?}", write_options.sex()); println!("{0:?}", write_options.pheno());
println!("{0:?}", write_options.chromosome()); println!("{0:?}", write_options.sid()); println!("{0:?}", write_options.cm_position()); println!("{0:?}", write_options.bp_position()); println!("{0:?}", write_options.allele_1()); println!("{0:?}", write_options.allele_2());
let metadata = write_options.metadata();
println!("{0:?}", metadata.iid());
assert_eq!(write_options.iid_count(), 3);
assert_eq!(write_options.sid_count(), 4);
assert_eq!(write_options.dim(), (3, 4));
let val = nd::array![
[1.0, 0.0, f64::NAN, 0.0],
[2.0, 0.0, f64::NAN, 2.0],
[0.0, 1.0, 2.0, 0.0]
];
Bed::write_with_options(&val, &write_options)?;
Ok(())
}
#[test]
fn write_options_builder() -> Result<(), Box<BedErrorPlus>> {
let output_folder = TempDir::default();
let output_file = output_folder.join("small.bed");
let val = nd::array![[1, 0, -127, 0], [2, 0, -127, 2], [0, 1, 2, 0]];
WriteOptions::builder(output_file)
.num_threads(1)
.write(&val)?;
let output_folder = TempDir::default();
let output_file = output_folder.join("small.deb");
let val = nd::array![[1, 0, -127, 0], [2, 0, -127, 2], [0, 1, 2, 0]];
WriteOptions::builder(output_file)
.fam_path(output_folder.join("small.maf"))
.bim_path(output_folder.join("small.mib"))
.write(&val)?;
Ok(())
}
#[test]
fn bed_inconsistent_count() -> Result<(), Box<BedErrorPlus>> {
let metadata = Metadata::builder().iid(["f1", "f2", "f3", "f4"]).build()?;
let result = Bed::builder(sample_bed_file("small.bed")?)
.fid(["f1", "f2", "f3"])
.metadata(&metadata)
.build();
assert_error_variant!(
result,
BedErrorPlus::BedError(BedError::InconsistentCount(_, _, _))
);
let mut bed = Bed::builder(sample_bed_file("small.bed")?)
.fam_path(sample_file("small.fam_bad")?)
.skip_iid()
.skip_father()
.skip_mother()
.skip_sex()
.skip_pheno()
.build()?;
let result = bed.fid();
assert_error_variant!(
result,
BedErrorPlus::BedError(BedError::MetadataFieldCount(_, _, _))
);
let result = Bed::builder(sample_bed_file("small.bed")?)
.fid(["f1", "f2", "f3"])
.iid(["i1", "i2", "i3", "i4"])
.build();
assert_error_variant!(
result,
BedErrorPlus::BedError(BedError::InconsistentCount(_, _, _))
);
let mut bed = Bed::builder(sample_bed_file("small.bed")?)
.iid(["i1", "i2", "i3", "i4"])
.build()?;
let result = bed.fid();
assert_error_variant!(
result,
BedErrorPlus::BedError(BedError::InconsistentCount(_, _, _))
);
Ok(())
}
#[test]
fn write_options_inconsistent_count() -> Result<(), Box<BedErrorPlus>> {
let temp_out = TempDir::default();
let output_file = temp_out.join("small.bed");
let metadata = Metadata::builder().build()?;
let result = WriteOptions::builder(&output_file)
.i8()
.fid(["f1", "f2", "f3", "f4"])
.metadata(&metadata)
.build(3, 4);
assert_error_variant!(
result,
BedErrorPlus::BedError(BedError::InconsistentCount(_, _, _))
);
let metadata = Metadata::builder().iid(["f1", "f2", "f3", "f4"]).build()?;
let result = WriteOptions::builder(&output_file)
.i8()
.metadata(&metadata)
.build(3, 4);
assert_error_variant!(
result,
BedErrorPlus::BedError(BedError::InconsistentCount(_, _, _))
);
Ok(())
}
#[test]
fn metadata_inconsistent_count() -> Result<(), Box<BedErrorPlus>> {
let skip_set = HashSet::<MetadataFields>::new();
let metadata = Metadata::builder().iid(["i1", "i2", "i3", "i4"]).build()?;
let result = metadata.read_fam(sample_file("small.fam")?, &skip_set);
assert_error_variant!(
result,
BedErrorPlus::BedError(BedError::InconsistentCount(_, _, _))
);
let metadata = Metadata::builder().iid(["f1", "f2", "f3", "f4"]).build()?;
let result = Metadata::builder()
.fid(["f1", "f2", "f3"])
.metadata(&metadata)
.build();
assert_error_variant!(
result,
BedErrorPlus::BedError(BedError::InconsistentCount(_, _, _))
);
let metadata = Metadata::builder().build()?;
let result = metadata.read_fam(sample_file("small.fam_bad")?, &skip_set);
assert_error_variant!(
result,
BedErrorPlus::BedError(BedError::MetadataFieldCount(_, _, _))
);
let result = Metadata::builder()
.fid(["f1", "f2", "f3"])
.iid(["i1", "i2", "i3", "i4"])
.build();
assert_error_variant!(
result,
BedErrorPlus::BedError(BedError::InconsistentCount(_, _, _))
);
let metadata = Metadata::builder().iid(["i1", "i2", "i3", "i4"]).build()?;
let result = metadata.fill(3, 4);
assert_error_variant!(
result,
BedErrorPlus::BedError(BedError::InconsistentCount(_, _, _))
);
Ok(())
}
#[test]
fn write_options_examples() -> Result<(), Box<BedErrorPlus>> {
let output_folder = TempDir::default();
let output_file = output_folder.join("small.bed");
let write_options = WriteOptions::builder(output_file)
.i8()
.iid(["i1", "i2", "i3"])
.sid(["s1", "s2", "s3", "s4"])
.build(3, 4)?;
assert!(write_options.is_a1_counted());
assert!(write_options.num_threads().is_none());
assert!(write_options.missing_value() == -127);
Ok(())
}
#[test]
fn parsing_metadata() -> Result<(), Box<BedErrorPlus>> {
let bed_fam_bim = sample_files(["small.bed", "small.fam", "small.bim_bad_positions.bim"])?;
let mut bed = Bed::builder(&bed_fam_bim[0])
.bim_path(&bed_fam_bim[2])
.build()?;
let result = bed.cm_position();
assert_error_variant!(result, BedErrorPlus::ParseIntError(_));
Ok(())
}
#[test]
fn read_fam() -> Result<(), Box<BedErrorPlus>> {
let skip_set = HashSet::<MetadataFields>::new();
let metadata_empty = Metadata::new();
let (metadata_fam, _) = metadata_empty.read_fam(sample_file("small.fam")?, &skip_set)?;
println!("{:?}", metadata_fam.iid()); Ok(())
}
#[test]
fn lib_intro() -> Result<(), Box<BedErrorPlus>> {
let file_name = sample_bed_file("some_missing.bed")?;
let mut bed = Bed::new(file_name)?;
println!("{:?}", bed.iid()?.slice(s![..5])); println!("{:?}", bed.sid()?.slice(s![..5])); println!("{:?}", bed.chromosome()?.iter().collect::<HashSet<_>>());
let _ = ReadOptions::builder()
.sid_index(bed.chromosome()?.map(|elem| elem == "5"))
.f64()
.read(&mut bed)?;
Ok(())
}
#[test]
fn metadata_iid_sid2() -> Result<(), Box<BedErrorPlus>> {
let metadata = Metadata::builder()
.iid(["sample1", "sample2", "sample3"])
.build()?;
println!("{:?}", metadata.iid());
let metadata = Metadata::builder()
.sid(["SNP1", "SNP2", "SNP3", "SNP4"])
.build()?;
println!("{:?}", metadata.sid());
Ok(())
}