1
+ use serde:: Deserialize ;
2
+
1
3
use crate :: core:: haplotype:: Symbol ;
2
4
use crate :: core:: population:: Population ;
3
5
use crate :: encoding:: DECODE ;
6
+ use crate :: errors:: { Result , VirolutionError } ;
4
7
use crate :: references:: HaplotypeRef ;
5
- use serde:: Deserialize ;
6
8
7
9
pub trait PopulationIO {
8
- fn read ( path : & str , wildtype : HaplotypeRef ) -> Result < Population , csv :: Error > ;
10
+ fn read ( path : & str , wildtype : HaplotypeRef ) -> Result < Population > ;
9
11
fn write ( & self , path : & str ) ;
10
12
}
11
13
@@ -20,30 +22,26 @@ impl PopulationIO for Population {
20
22
///
21
23
/// Warning: This function will create multiple instances of the same
22
24
/// haplotype if it is present multiple times in the CSV file.
23
- fn read ( path : & str , wildtype : HaplotypeRef ) -> Result < Population , csv:: Error > {
24
- let mut reader = csv:: Reader :: from_path ( path) ?;
25
+ fn read ( path : & str , wildtype : HaplotypeRef ) -> Result < Population > {
26
+ let mut reader = csv:: Reader :: from_path ( path)
27
+ . map_err ( |_err| VirolutionError :: ReadError ( format ! ( "Failed to read from {path}" ) ) ) ?;
25
28
let mut populations: Vec < Population > = Vec :: new ( ) ;
26
29
27
30
for record in reader. deserialize ( ) {
28
- let record: HaplotypeRecord = record?;
31
+ let record: HaplotypeRecord = record. map_err ( |_err| {
32
+ VirolutionError :: ReadError ( format ! ( "Failed to parse record in {path}" ) )
33
+ } ) ?;
34
+
35
+ // skip wildtype
29
36
if record. haplotype == "wt" {
30
37
continue ;
31
38
}
32
- let mutations = record. haplotype . split ( ';' ) ;
33
- let mut positions: Vec < usize > = Vec :: new ( ) ;
34
- let mut changes: Vec < Symbol > = Vec :: new ( ) ;
35
- mutations. for_each ( |mutation| {
36
- let mut mutation = mutation. split ( ':' ) ;
37
- let position = mutation. next ( ) . unwrap ( ) ;
38
-
39
- let mut change = mutation. next ( ) . unwrap ( ) . split ( "->" ) ;
40
- let _origin = change. next ( ) ;
41
- let target = change. next ( ) . unwrap ( ) . chars ( ) . next ( ) . unwrap ( ) as u8 ;
42
-
43
- positions. push ( position. parse :: < usize > ( ) . unwrap ( ) ) ;
44
- changes. push ( DECODE . get ( & target) . copied ( ) ) ;
45
- } ) ;
39
+
40
+ // parse haplotype
41
+ let ( positions, changes) = parse_haplotype ( & record. haplotype ) ?;
46
42
let haplotype = wildtype. create_descendant ( positions, changes, 0 ) ;
43
+
44
+ // create population and add for merging
47
45
let population = Population :: from_haplotype ( haplotype, record. count ) ;
48
46
populations. push ( population) ;
49
47
}
@@ -55,3 +53,37 @@ impl PopulationIO for Population {
55
53
unimplemented ! ( )
56
54
}
57
55
}
56
+
57
+ fn parse_haplotype ( haplotype : & str ) -> Result < ( Vec < usize > , Vec < Symbol > ) > {
58
+ let mutations = haplotype. split ( ';' ) ;
59
+ let parsed_mutations: Result < Vec < ( usize , Symbol ) > > = mutations. map ( parse_mutation) . collect ( ) ;
60
+ Ok ( parsed_mutations?. into_iter ( ) . unzip ( ) )
61
+ }
62
+
63
+ fn parse_mutation ( mutation : & str ) -> Result < ( usize , Symbol ) > {
64
+ let mutation_split: Vec < & str > = mutation. split ( ':' ) . collect ( ) ;
65
+ match mutation_split. as_slice ( ) {
66
+ [ position, change] => Ok ( (
67
+ position. parse :: < usize > ( ) . map_err ( |_| {
68
+ VirolutionError :: ReadError ( format ! ( "Failed to parse position: {position}" ) )
69
+ } ) ?,
70
+ parse_change ( change) ?,
71
+ ) ) ,
72
+ _ => Err ( VirolutionError :: ReadError ( format ! (
73
+ "Invalid mutation format: {mutation}"
74
+ ) ) ) ,
75
+ }
76
+ }
77
+
78
+ fn parse_change ( change : & str ) -> Result < Symbol > {
79
+ let change_split: Vec < & str > = change. split ( ':' ) . collect ( ) ;
80
+ match change_split. as_slice ( ) {
81
+ [ _origin, target] => {
82
+ let target = target. chars ( ) . next ( ) . unwrap ( ) as u8 ;
83
+ Ok ( DECODE . get ( & target) . copied ( ) )
84
+ }
85
+ _ => Err ( VirolutionError :: ReadError ( format ! (
86
+ "Invalid change format: {change}"
87
+ ) ) ) ,
88
+ }
89
+ }
0 commit comments