| 431 | } |
| 432 | |
| 433 | pub fn quantile_mapping(array: &[f64], num_letters: usize) -> Result<Vec<(f64, char)>, String> { |
| 434 | if num_letters == 0 || num_letters > 256 { |
| 435 | return Err("num_letters out of range".into()); |
| 436 | } |
| 437 | let table = ascii_table(); |
| 438 | let alphabet = &table[..num_letters]; |
| 439 | let mut sorted = array.to_vec(); |
| 440 | sorted.sort_by(|a, b| a.partial_cmp(b).unwrap()); |
| 441 | let mut out: Vec<(f64, char)> = Vec::new(); |
| 442 | for (q, letter) in linspace(0.01, 1.0, alphabet.len()).iter().zip(alphabet.iter()) { |
| 443 | let idx = ((*q) * (sorted.len() as f64 - 1.0)).round() as usize; |
| 444 | out.push((sorted[idx], *letter)); |
| 445 | } |
| 446 | Ok(out) |
| 447 | } |
| 448 | |
| 449 | fn linspace(start: f64, end: f64, n: usize) -> Vec<f64> { |
| 450 | if n == 0 { |