1use indicatif::{ProgressBar, ProgressStyle};
3use std::collections::HashSet;
4use std::hash::Hash;
5
6pub fn vec2set<T: Eq + Hash>(x: Vec<T>) -> HashSet<T> {
8 x.into_iter().collect::<HashSet<T>>()
9}
10
11pub fn seq_to_int(seq: &str) -> u64 {
13 assert!(seq.len() <= 32); let s: String = seq
15 .chars()
16 .map(|x| match x {
17 'A' => '0',
18 'C' => '1',
19 'G' => '2',
20 'T' => '3',
21 c => panic!("unkown seq character {}", c),
22 })
23 .collect();
24 u64::from_str_radix(&s, 4).unwrap()
25}
26
27pub fn int_to_seq(i: u64, seq_len: usize) -> String {
29 let mut q = i;
30 let mut result: Vec<u64> = Vec::with_capacity(seq_len);
31 while q >= 4 {
32 let quotient = q / 4;
33 let remainder = q % 4;
34 result.push(remainder);
35 q = quotient;
36 }
37 result.push(q);
38
39 while result.len() < seq_len {
40 result.push(0);
41 }
42 result.reverse();
43
44 let s: String = result
45 .iter()
46 .map(|x| match x {
47 0 => 'A',
48 1 => 'C',
49 2 => 'G',
50 3 => 'T',
51 c => panic!("unkown seq character {}", c),
52 })
53 .collect();
55 s
56}
57
58pub fn get_progressbar(total: u64) -> ProgressBar {
60 let bar = ProgressBar::new(total);
61 bar.set_style(
62 ProgressStyle::default_bar()
63 .template("[{elapsed_precise} ETA {eta}] {bar:40.cyan/blue} {pos}/{len} {per_sec}")
64 .unwrap()
65 .progress_chars("##-"),
66 );
67 bar
68}
69
70pub fn get_spinner() -> indicatif::ProgressBar{
71 let bar = indicatif::ProgressBar::new_spinner();
72 bar.set_style(
73 indicatif::ProgressStyle::default_bar()
74 .template("[{elapsed_precise}] {pos} {per_sec}")
75 .unwrap()
76 .progress_chars("##-"),
77 );
78 bar
79}
80
81pub mod argsort {
82 use std::cmp::Ordering;
96
97 #[derive(PartialEq, PartialOrd)]
98 struct NonNan(f64);
99
100 impl NonNan {
101 fn new(val: f64) -> Option<NonNan> {
102 if val.is_nan() {
103 None
104 } else {
105 Some(NonNan(val))
106 }
107 }
108 }
109 impl Eq for NonNan {}
110
111 impl Ord for NonNan {
112 fn cmp(&self, other: &NonNan) -> Ordering {
113 self.partial_cmp(other).unwrap()
114 }
115 }
116
117 pub fn argsort<T: Ord>(slice: &[T]) -> Vec<usize> {
119 let n = slice.len();
120 let mut keys: Vec<_> = (0..n).collect();
121 keys.sort_by_key(|x| &slice[*x]);
122 keys
123 }
124
125 pub fn argsort_float(fvec: &Vec<f64>, ascending: bool) -> Vec<usize> {
127 let _fvec: Vec<NonNan> = fvec
128 .iter()
129 .map(|x| NonNan::new(*x).unwrap_or_else(|| panic!("Nan values in {fvec:?}")))
130 .collect();
131
132 let mut fvec_sorted_ix = argsort(&_fvec);
133 if ascending {
134 fvec_sorted_ix.reverse();
135 }
136 fvec_sorted_ix
137 }
138
139 pub fn argmax_float(fvec: &Vec<f64>) -> (usize, f64) {
141 let ix = argsort_float(fvec, true);
142 let i = ix[0];
143 let value = fvec[i];
144 (i, value)
145 }
146
147 pub fn argmin_float(fvec: &Vec<f64>) -> (usize, f64) {
149 let ix = argsort_float(fvec, false);
150 let i = ix[0];
151 let value = fvec[i];
152 (i, value)
153 }
154
155 #[test]
156 fn test_argmin() {
157 let v = vec![1.0, -1.0, 10.0, 0.0];
158 assert_eq!(argmin_float(&v), (1, -1.0));
159 }
160
161 #[test]
162 fn test_argmax() {
163 let v = vec![1.0, -1.0, 10.0, 0.0];
164 assert_eq!(argmax_float(&v), (2, 10.0));
165 }
166}
167
168pub fn min_argmin<T: Ord+ Copy>(x: &[T]) -> (T, Vec<usize>){
170
171 if x.len() == 1 {
172 (x[0], vec![0])
173 } else {
174 let mut current_min: &T = x.first().expect("x has to contain an element");
175 let mut indices: Vec<usize> = Vec::with_capacity(x.len());
176 indices.push(0);
177
178 for (ix, el) in x.iter().enumerate().skip(1) {
179 match el.cmp(current_min) {
180 std::cmp::Ordering::Less => {
181 current_min = el;
183 indices = vec![ix]
184 },
185 std::cmp::Ordering::Equal => {
186 indices.push(ix)
188 },
189 std::cmp::Ordering::Greater => { },
190 }
191 }
192
193 (*current_min, indices)
194 }
195}
196#[test]
197fn test_min_argmin() {
198
199 let x = vec![4,3,2,1];
201 assert_eq!(
202 min_argmin(&x),
203 (1, vec![3])
204 );
205
206 let x = vec![4,1,2,1];
208 assert_eq!(
209 min_argmin(&x),
210 (1, vec![1,3])
211 );
212
213 let x = vec![4, 2, 3, 2, 1, 2, 1, 4];
215 assert_eq!(
216 min_argmin(&x),
217 (1, vec![4, 6])
218 );
219}
220
221#[cfg(test)]
222mod tests {
223 #[test]
224 fn encode_seq() {
225 use crate::utils::seq_to_int;
226 assert_eq!(seq_to_int("A"), 0);
227 assert_eq!(seq_to_int("C"), 1);
228 assert_eq!(seq_to_int("G"), 2);
229 assert_eq!(seq_to_int("T"), 3);
230 assert_eq!(seq_to_int("GCCA"), 148);
231 }
232
233 #[test]
234 fn decode_seq() {
235 use crate::utils::int_to_seq;
236
237 assert_eq!(int_to_seq(0, 1), "A");
239 assert_eq!(int_to_seq(1, 1), "C");
240 assert_eq!(int_to_seq(2, 1), "G");
241 assert_eq!(int_to_seq(3, 1), "T");
242 assert_eq!(int_to_seq(0, 3), "AAA");
245 assert_eq!(int_to_seq(1, 3), "AAC");
246 assert_eq!(int_to_seq(2, 3), "AAG");
247 assert_eq!(int_to_seq(3, 3), "AAT");
248 assert_eq!(int_to_seq(4, 2), "CA");
250 assert_eq!(int_to_seq(5, 2), "CC");
251 assert_eq!(int_to_seq(6, 2), "CG");
252 assert_eq!(int_to_seq(7, 2), "CT");
253 assert_eq!(int_to_seq(148, 4), "GCCA");
255 }
263}