Skip to main content

knuckles_parse/records/
anisotropic.rs

1#[cfg(feature = "serde")]
2use serde::{Deserialize, Serialize};
3
4#[cfg(feature = "python")]
5use pyo3::prelude::*;
6
7#[cfg(feature = "python")]
8use knuckles_macro::pydefault;
9
10#[derive(Debug, Clone)]
11#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
12#[cfg_attr(feature = "python", pyclass(get_all, set_all))]
13#[cfg_attr(feature = "python", pydefault)]
14pub struct AnisotropicRecord {
15    pub serial: u32,
16    pub name: String,
17    pub alt_loc: Option<char>,
18    pub res_name: String,
19    pub chain_id: char,
20    pub res_seq: i16,
21    pub i_code: Option<char>,
22    pub u00: i32,
23    pub u11: i32,
24    pub u22: i32,
25    pub u01: i32,
26    pub u02: i32,
27    pub u12: i32,
28    pub element: Option<String>,
29    pub charge: Option<String>,
30}
31
32impl AnisotropicRecord {
33    pub fn new(str: &str) -> AnisotropicRecord {
34        AnisotropicRecord {
35            serial: str[6..11].trim().parse::<u32>().unwrap_or_default(),
36            name: str[12..16].trim().to_string(),
37            alt_loc: str[16..17].trim().parse::<char>().ok(),
38            res_name: str[17..20].trim().to_string(),
39            chain_id: str[21..22].trim().parse::<char>().unwrap(),
40            res_seq: str[22..26].trim().parse().unwrap(),
41            i_code: str[26..27].trim().parse::<char>().ok(),
42            u00: str[28..35].trim().parse().unwrap(),
43            u11: str[35..42].trim().parse().unwrap(),
44            u22: str[42..49].trim().parse().unwrap(),
45            u01: str[49..56].trim().parse().unwrap(),
46            u02: str[56..63].trim().parse().unwrap(),
47            u12: str[63..70].trim().parse().unwrap(),
48            element: str
49                .get(76..78)
50                .map(|str| str.trim().to_string())
51                .filter(|item| !item.is_empty()),
52            charge: str
53                .get(78..80)
54                .map(|str| str.trim().to_string())
55                .filter(|item| !item.is_empty()),
56        }
57    }
58}
59
60impl From<&str> for AnisotropicRecord {
61    fn from(str: &str) -> Self {
62        AnisotropicRecord::new(str)
63    }
64}
65
66#[cfg(test)]
67mod tests {
68    use super::*;
69
70    #[test]
71    fn parse_anisou_line_test() {
72        const LINE: &str =
73            "ANISOU    1  N   MET A   1      688   1234    806    -19    -49    178       N  ";
74        let record = AnisotropicRecord::new(LINE);
75        assert_eq!(record.serial, 1);
76        assert_eq!(record.name, "N");
77        assert_eq!(record.res_name, "MET");
78        assert_eq!(record.chain_id, 'A');
79        assert_eq!(record.res_seq, 1);
80        assert_eq!(record.u00, 688);
81        assert_eq!(record.u11, 1234);
82        assert_eq!(record.u22, 806);
83        assert_eq!(record.u01, -19);
84        assert_eq!(record.u02, -49);
85        assert_eq!(record.u12, 178);
86        assert_eq!(record.element, Some("N".to_string()));
87        const LINE2: &str =
88            "ANISOU    1  N   MET A   1      688   1234    806    -19    -49    178          ";
89        let record = AnisotropicRecord::new(LINE2);
90        assert_eq!(record.serial, 1);
91        assert_eq!(record.name, "N");
92        assert_eq!(record.res_name, "MET");
93        assert_eq!(record.chain_id, 'A');
94        assert_eq!(record.res_seq, 1);
95        assert_eq!(record.u00, 688);
96        assert_eq!(record.u11, 1234);
97        assert_eq!(record.u22, 806);
98        assert_eq!(record.u01, -19);
99        assert_eq!(record.u02, -49);
100        assert_eq!(record.u12, 178);
101        assert_eq!(record.element, None);
102    }
103}