Skip to content

Commit

Permalink
Merge pull request #34 from jeffersonfparil/dev
Browse files Browse the repository at this point in the history
Improving error handling with chainable custom error type: ImputefError (see issue #30)
  • Loading branch information
jeffersonfparil authored May 20, 2024
2 parents b11162c + 673b094 commit 651450a
Show file tree
Hide file tree
Showing 9 changed files with 1,696 additions and 605 deletions.
439 changes: 323 additions & 116 deletions src/aldknni.rs

Large diffs are not rendered by default.

101 changes: 67 additions & 34 deletions src/filter_missing.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use ndarray::prelude::*;
use std::io::{self, Error, ErrorKind};

use crate::helpers::*;
use crate::structs_and_traits::*;
Expand All @@ -9,18 +8,19 @@ impl GenotypesAndPhenotypes {
&mut self,
min_depth_below_which_are_missing: &f64,
max_depth_above_which_are_missing: &f64,
) -> io::Result<&mut Self> {
self.check().expect("Error calling check() method within set_missing_by_depth() method for GenotypesAndPhenotypes struct.");
) -> Result<&mut Self, ImputefError> {
match self.check() {
Ok(x) => x,
Err(e) => return Err(ImputefError {
code: 201,
message:
"Error checking GenotypesAndPhenotypes in the method set_missing_by_depth() | "
.to_owned()
+ &e.message,
}),
};
let (n, _p) = self.intercept_and_allele_frequencies.dim();
let (_n, l) = self.coverages.dim();
// println!(
// "self.intercept_and_allele_frequencies.dim()={:?}",
// self.intercept_and_allele_frequencies.dim()
// );
// println!("self.chromosome.len()={:?}", self.chromosome.len());
// println!("self.position.len()={:?}", self.position.len());
// println!("self.allele.len()={:?}", self.allele.len());
// println!("self.coverages.dim()={:?}", self.coverages.dim());
let (loci_idx, _loci_chr, _loci_pos) = self.count_loci().expect("Error defining loci indexes and identities via count_loci() method within set_missing_by_depth() method for GenotypesAndPhenotypes struct.");
for i in 0..n {
for j in 0..l {
Expand All @@ -37,11 +37,20 @@ impl GenotypesAndPhenotypes {
}
}
}
self.check().expect("Error calling check() method within set_missing_by_depth() method for GenotypesAndPhenotypes struct.");
match self.check() {
Ok(x) => x,
Err(e) => return Err(ImputefError {
code: 202,
message:
"Error checking GenotypesAndPhenotypes in the method set_missing_by_depth() | "
.to_owned()
+ &e.message,
}),
};
Ok(self)
}

pub fn missing_rate(&mut self) -> io::Result<f64> {
pub fn missing_rate(&mut self) -> Result<f64, ImputefError> {
let (n, l) = self.coverages.dim();
let sum = self.coverages.fold(0, |sum, &x| {
if (x.is_nan()) || (x == 0.0) {
Expand All @@ -50,14 +59,21 @@ impl GenotypesAndPhenotypes {
sum
}
});
Ok(sensible_round(sum as f64 * 100.0 / ((n * l) as f64), 5))
sensible_round(sum as f64 * 100.0 / ((n * l) as f64), 5)
}

pub fn filter_out_top_missing_pools(
&mut self,
frac_top_missing_pools: &f64,
) -> io::Result<&mut Self> {
self.check().expect("Error calling check() method within filter_out_top_missing_pools() method for GenotypesAndPhenotypes struct.");
) -> Result<&mut Self, ImputefError> {
match self.check() {
Ok(x) => x,
Err(e) => return Err(ImputefError{
code: 203,
message: "Error checking GenotypesAndPhenotypes in the method filter_out_top_missing_pools() | ".to_owned() +
&e.message
})
};
let n = self.intercept_and_allele_frequencies.nrows();
let p = self.intercept_and_allele_frequencies.ncols() - 1;
let missingness_per_pool: Array1<f64> = self
Expand All @@ -75,10 +91,11 @@ impl GenotypesAndPhenotypes {
missingness_per_pool.fold(0.0, |sum, &x| if x > 0.0 { sum + 1.0 } else { sum });
let n_after_filtering = n - (n_missing * frac_top_missing_pools).ceil() as usize;
if n_after_filtering == 0 {
return Err(Error::new(
ErrorKind::Other,
"No pools left after filtering, please reduce 'frac_top_missing_pools'".to_owned(),
));
return Err(ImputefError {
code: 204,
message: "No pools left after filtering, please reduce 'frac_top_missing_pools'"
.to_owned(),
});
}
// Sort by increasing missingness
let mut idx = (0..n).collect::<Vec<usize>>();
Expand Down Expand Up @@ -127,16 +144,30 @@ impl GenotypesAndPhenotypes {
// println!("self.allele.len()={:?}", self.allele.len());
// println!("self.intercept_and_allele_frequencies.dim()={:?}", self.intercept_and_allele_frequencies.dim());
// println!("self.coverages.len()={:?}", self.coverages.dim());
self.check().expect("Error calling check() method within filter_out_top_missing_pools() method for GenotypesAndPhenotypes struct.");
match self.check() {
Ok(x) => x,
Err(e) => return Err(ImputefError{
code: 205,
message: "Error checking GenotypesAndPhenotypes in the method filter_out_top_missing_pools() | ".to_owned() +
&e.message
})
};
Ok(self)
}

// For thinning the data before imputation and also removing completely missing loci after imputation
pub fn filter_out_top_missing_loci(
&mut self,
frac_top_missing_loci: &f64,
) -> io::Result<&mut Self> {
self.check().expect("Error calling check() method within filter_out_top_missing_loci() method for GenotypesAndPhenotypes struct.");
) -> Result<&mut Self, ImputefError> {
match self.check() {
Ok(x) => x,
Err(e) => return Err(ImputefError{
code: 206,
message: "Error checking GenotypesAndPhenotypes in the method filter_out_top_missing_loci() | ".to_owned() +
&e.message
})
};
let n = self.intercept_and_allele_frequencies.nrows();
let (loci_idx, _loci_chr, _loci_pos) = self.count_loci().expect("Error calling count_loci() method within filter_out_top_missing_loci() method for GenotypesAndPhenotypes struct.");
let l = loci_idx.len() - 1; // Less one for the trailing locus
Expand All @@ -159,10 +190,11 @@ impl GenotypesAndPhenotypes {
// Define the number of loci kept after filtering
let l_after_filtering = l - (l_missing * frac_top_missing_loci).ceil() as usize;
if l_after_filtering == 0 {
return Err(Error::new(
ErrorKind::Other,
"No loci left after filtering, please reduce 'frac_top_missing_loci'".to_owned(),
));
return Err(ImputefError {
code: 207,
message: "No loci left after filtering, please reduce 'frac_top_missing_loci'"
.to_owned(),
});
}
// Sort by increasing missingness
let mut idx = (0..l).collect::<Vec<usize>>();
Expand Down Expand Up @@ -224,13 +256,14 @@ impl GenotypesAndPhenotypes {
self.allele = new_allele;
self.intercept_and_allele_frequencies = new_intercept_and_allele_frequencies;
self.coverages = new_coverages;
// println!("self={:?}", self);
// println!("self.chromosome.len()={:?}", self.chromosome.len());
// println!("self.position.len()={:?}", self.position.len());
// println!("self.allele.len()={:?}", self.allele.len());
// println!("self.intercept_and_allele_frequencies.dim()={:?}", self.intercept_and_allele_frequencies.dim());
// println!("self.coverages.len()={:?}", self.coverages.dim());
self.check().expect("Error calling check() method within filter_out_top_missing_loci() method for GenotypesAndPhenotypes struct.");
match self.check() {
Ok(x) => x,
Err(e) => return Err(ImputefError{
code: 208,
message: "Error checking GenotypesAndPhenotypes in the method filter_out_top_missing_loci() | ".to_owned() +
&e.message
})
};
Ok(self)
}
}
Expand Down
Loading

0 comments on commit 651450a

Please sign in to comment.