Skip to main content

debruijn/
serde.rs

1use std::fmt::Debug;
2use std::hash::Hash;
3use std::path::Path;
4use std::{fs::File, io::{BufReader, BufWriter}};
5
6use boomphf::hashmap::BoomHashMap2;
7use serde::{de::DeserializeOwned, Deserialize, Serialize};
8
9use crate::graph::DebruijnGraph;
10use crate::reads::{ReadData, ReadDatas};
11use crate::summarizer::{Summarizers, SummaryConfig, SummaryData, Translator};
12use crate::Kmer;
13use crate::{reads::ReadsPaired, Exts};
14
15/// serialize a [`ReadsPaired`] together with its hashed tags and IDs
16#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone)]
17pub struct SerReads<DI> {
18    reads: ReadsPaired<DI>,
19    read_datas: ReadDatas,
20    translator: Translator
21}
22
23impl<DI> SerReads<DI> {
24    /// make a new [`SerReads`]
25    pub fn new(reads: ReadsPaired<DI>, translator: Translator) -> SerReads<DI> 
26    where DI: ReadData
27    {
28        SerReads {
29            reads,
30            read_datas: DI::read_datas(),
31            translator
32        }
33    }
34
35    /// serialize a [`SerReads`]
36    pub fn serialize<P: AsRef<Path>>(&self, path: P) 
37    where DI: Serialize
38    {
39        let file = File::create(path).expect("error creating file for serialized reads");
40        let writer = BufWriter::new(file);
41        bincode::serialize_into(writer, &self).expect("error serializing reads");
42    }
43
44    /// deserialize a [`SerReads`]
45    pub fn deserialize_from<P: AsRef<Path> + Debug>(path: P) -> SerReads<DI> 
46    where DI: DeserializeOwned
47    {
48        let file = File::open(&path).expect("error opening file with serialized reads");
49        let reader = BufReader::new(file);
50
51        match bincode::deserialize_from(reader) {
52            Ok(ser_reads) => ser_reads,
53            Err(err) => panic!("Error deserializing cached reads: {}\n Make sure the file was cached with a compatible version and parameters. \nFile: {:?}", err, path)
54        }
55    }
56
57    /// get a reference of the underlying [`ReadsPaired<DI>`]
58    pub fn reads(&self) -> &ReadsPaired<DI> {
59        &self.reads
60    }
61
62    /// get a reference of the underlying translator (hashed tags & IDs)
63    pub fn translator(&self) -> &Translator {
64        &self.translator
65    }
66
67    /// get the parameters (read data kind)
68    pub fn parameters(&self) -> ReadDatas {
69        self.read_datas
70    }
71
72    /// get the underlying read, hashed tags and hashed labels
73    pub fn dissolve(self) -> (ReadsPaired<DI>, Translator) {
74        (self.reads, self.translator)
75    }
76}
77
78
79/// serialize a [`SerKmers`] together with its hashed tags and IDs and a config
80#[derive(Debug, Serialize, Deserialize, Clone)]
81pub struct SerKmers<K: Hash, SD> {
82    kmers: BoomHashMap2<K, Exts, SD>,
83    k: usize,
84    summarizer: Summarizers,
85    translator: Translator,
86    config: SummaryConfig
87}
88
89impl<K: Kmer, SD> SerKmers<K, SD> {
90    /// make a new [`SerKmers`]
91    pub fn new<DI>(kmers: BoomHashMap2<K, Exts, SD>, translator: Translator, config: SummaryConfig) -> SerKmers<K, SD> 
92    where SD: SummaryData<DI>
93    {
94        SerKmers {
95            kmers,
96            summarizer: SD::summarizer(),
97            k: K::k(),
98            translator,
99            config
100        }
101    }
102
103    /// serialize a [`SerKmers`]
104    pub fn serialize<P: AsRef<Path>>(&self, path: P) 
105    where 
106        K: Serialize,
107        SD: Serialize
108    {
109        let file = File::create(path).expect("error creating file for serialized k-mers");
110        let writer = BufWriter::new(file);
111        bincode::serialize_into(writer, &self).expect("error serializing k-mers");
112    }
113
114    /// deserialize a [`SerKmers`]
115    pub fn deserialize_from<P: AsRef<Path> + Debug, DI>(path: P) -> SerKmers<K, SD> 
116    where
117        K: DeserializeOwned,
118        SD: DeserializeOwned + SummaryData<DI>
119    {
120        let file = File::open(&path).expect("error opening file with serialized k-mers");
121        let reader = BufReader::new(file);
122
123        let ser_kmers: SerKmers<K, SD> = match bincode::deserialize_from(reader) {
124            Ok(ser_kmers) => ser_kmers,
125            Err(err) => panic!("Error deserializing cached k-mers: {}\n Make sure the file was cached with a compatible version and parameters. \nFile: {:?}", err, path)
126        };
127
128        assert_eq!(ser_kmers.parameters().0, K::k(), "deserialized k-kmers do not match expected k");
129        assert_eq!(ser_kmers.parameters().1, SD::summarizer(), "deserialized k-mers do not match expected summarizer");
130
131        ser_kmers
132    }
133
134    /// get a reference of the underlying [`BoomHashMap2<K, Exts, SD>`]
135    pub fn kmers(&self) -> &BoomHashMap2<K, Exts, SD> {
136        &self.kmers
137    }
138
139    /// get a reference of the underlying translator (hashed tags & IDs)
140    pub fn translator(&self) -> &Translator {
141        &self.translator
142    }
143
144    /// get a reference of the underlying config
145    pub fn config(&self) -> &SummaryConfig {
146        &self.config
147    }
148
149    /// get the set parameters (k, summarizer) of the `SerKmers`
150    pub fn parameters(&self) -> (usize, Summarizers) {
151        (self.k, self.summarizer)
152    }
153
154    /// get the underlying read, hashed tags, hashed labels and config
155    pub fn dissolve(self) -> (BoomHashMap2<K, Exts, SD>, Translator, SummaryConfig) {
156        (self.kmers, self.translator, self.config)
157    }
158}
159
160/// serialize a [`SerGraph`] together with its hashed tags and IDs and a config
161#[derive(Debug, Serialize, Deserialize)]
162pub struct SerGraph<K: Hash, SD> {
163    graph: DebruijnGraph<K, SD>,
164    summarizer: Summarizers,
165    k: usize,
166    translator: Translator,
167    config: SummaryConfig
168}
169
170impl<K: Kmer, SD> SerGraph<K, SD> {
171    /// make a new [`SerGraph`]
172    pub fn new<DI>(graph: DebruijnGraph<K, SD>, translator: Translator, config: SummaryConfig) -> SerGraph<K, SD> 
173    where SD: SummaryData<DI>
174    {
175        SerGraph {
176            graph,
177            summarizer: SD::summarizer(),
178            k: K::k(),
179            translator,
180            config
181        }
182    }
183
184    /// serialize a [`SerGraph`]
185    pub fn serialize<P: AsRef<Path>>(&self, path: P) 
186    where 
187        K: Serialize,
188        SD: Serialize
189    {
190        let file = File::create(path).expect("error creating file for a serialized graph");
191        let writer = BufWriter::new(file);
192        bincode::serialize_into(writer, &self).expect("error serializing graph");
193    }
194
195    /// deserialize a [`SerGraph`]
196    pub fn deserialize_from<P: AsRef<Path> + Debug, DI>(path: P) -> SerGraph<K, SD>  
197    where 
198        K: DeserializeOwned,
199        SD: DeserializeOwned + SummaryData<DI>
200    {
201        let file = File::open(&path).expect("error opening file with a serialized graph");
202        let reader = BufReader::new(file);
203
204        let ser_graph: SerGraph<K, SD> = match bincode::deserialize_from(reader) {
205            Ok(ser_graph) => ser_graph,
206            Err(err) => panic!("Error deserializing cached graph: {}\n Make sure the file was cached with a compatible version and parameters. \n File: {:?}", err, path)
207        };
208
209        assert_eq!(ser_graph.parameters().0, K::k(), "deserialized k-kmers do not match expected k");
210        assert_eq!(ser_graph.parameters().1, SD::summarizer(), "deserialized k-mers do not match expected summarizer");
211
212        ser_graph
213    }
214
215    /// get a reference of the underlying [`DebruijnGraph<K, SD>`]
216    pub fn graph(&self) -> &DebruijnGraph<K, SD> {
217        &self.graph
218    }
219
220    /// get a reference of the underlying translator (hashed tags and IDs)
221    pub fn translator(&self) -> &Translator {
222        &self.translator
223    }
224    /// get a reference of the underlying [`SummaryConfig`]
225    pub fn config(&self) -> &SummaryConfig {
226        &self.config
227    }
228
229    /// get the set parameters (k, summarizer) of the `SerGraph`
230    pub fn parameters(&self) -> (usize, Summarizers) {
231        (self.k, self.summarizer)
232    }
233
234    /// get the underlying graph, hashed tags, hashed labels and config
235    pub fn dissolve(self) -> (DebruijnGraph<K, SD>, Translator, SummaryConfig) {
236        (self.graph, self.translator, self.config)
237    }
238}
239
240#[cfg(test)]
241mod test {
242    use std::fs::remove_file;
243
244    use crate::{kmer::Kmer16, reads::ReadDatas, serde::{SerGraph, SerKmers}, summarizer::{IDSumData, IDTag, Summarizers}, test::build_test_graph};
245
246    use super::SerReads;
247
248    #[test]
249    fn test_ser_reads() {
250        let (ser_reads, _, _) = build_test_graph::<Kmer16, IDSumData, _>();
251
252        let cloned_ser_reads = ser_reads.clone();
253
254        let all = ser_reads.dissolve();
255        assert_eq!(cloned_ser_reads.reads(), &all.0);
256        assert_eq!(cloned_ser_reads.translator(), &all.1);
257        assert_eq!(cloned_ser_reads.parameters(), ReadDatas::IDTag);
258
259        let ser_reads = SerReads::new(all.0, all.1);
260        let ser_path = "test_data/new_ser_reads";
261        ser_reads.serialize(ser_path);
262
263        let new_ser_reads: SerReads<IDTag> = SerReads::deserialize_from(ser_path);
264        assert_eq!(ser_reads, new_ser_reads);
265        remove_file(ser_path).unwrap();
266    }
267
268    #[test]
269    fn test_ser_kmers() {
270        let (_, ser_kmers, _) = build_test_graph::<Kmer16, IDSumData, _>();
271
272        let cloned_ser_kmers = ser_kmers.clone();
273
274        let all = ser_kmers.dissolve();
275        assert_eq!(cloned_ser_kmers.kmers().len(), all.0.len());
276        assert_eq!(cloned_ser_kmers.translator(), &all.1);
277        assert_eq!(cloned_ser_kmers.config(), &all.2);
278        assert_eq!(cloned_ser_kmers.parameters(), (16, Summarizers::IDSumData));
279
280        let ser_kmers = SerKmers::new(all.0, all.1, all.2);
281        let ser_path = "test_data/new_ser_kmers";
282        ser_kmers.serialize(ser_path);
283
284        let new_ser_kmers: SerKmers<Kmer16, IDSumData> = SerKmers::deserialize_from(ser_path);
285        assert_eq!(ser_kmers.kmers().len(), new_ser_kmers.kmers().len());
286        assert_eq!(ser_kmers.translator(), new_ser_kmers.translator());
287        assert_eq!(ser_kmers.config(), new_ser_kmers.config());
288
289        remove_file(ser_path).unwrap();
290    }
291
292    #[test]
293    fn test_ser_graph() {
294        let (_, _, ser_graph) = build_test_graph::<Kmer16, IDSumData, _>();
295
296        let all = ser_graph.dissolve();
297
298        let ser_graph = SerGraph::new(all.0, all.1, all.2);
299        let ser_path = "test_data/new_ser_graph";
300        ser_graph.serialize(ser_path);
301
302        let new_ser_kmers: SerGraph<Kmer16, IDSumData> = SerGraph::deserialize_from(ser_path);
303        assert_eq!(ser_graph.graph().len(), new_ser_kmers.graph().len());
304        assert_eq!(ser_graph.translator(), new_ser_kmers.translator());
305        assert_eq!(ser_graph.config(), new_ser_kmers.config());
306        assert_eq!(ser_graph.parameters(), (16, Summarizers::IDSumData));
307
308        remove_file(ser_path).unwrap();
309    }
310}
311