1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
use crate::error::*;
use crate::structs::*;
pub fn validate(pdb: &PDB) -> Vec<PDBError> {
let mut errors = Vec::new();
if pdb.model_count() > 1 {
errors.append(&mut validate_models(pdb));
}
if pdb.has_scale() && !pdb.scale().valid() {
errors.push(PDBError::new(
ErrorLevel::InvalidatingError,
"Row not set",
"A row was not set for SCALEn in the PDB.",
Context::None,
));
}
if pdb.has_origx() && !pdb.origx().valid() {
errors.push(PDBError::new(
ErrorLevel::InvalidatingError,
"Row not set",
"A row was not set for ORIGXn in the PDB.",
Context::None,
));
}
for m in pdb.mtrix() {
if !m.valid() {
errors.push(PDBError::new(
ErrorLevel::InvalidatingError,
"Row not set",
&format!(
"A row was not set for MTRIXn Serial number {} in the PDB.",
m.serial_number()
),
Context::None,
));
}
}
errors
}
#[allow(clippy::unwrap_used)]
fn validate_models(pdb: &PDB) -> Vec<PDBError> {
let mut errors = Vec::new();
let total_atoms = pdb.model(0).unwrap().atom_count();
let total_hetero_atoms =
pdb.model(0).unwrap().total_atom_count() - pdb.model(0).unwrap().atom_count();
for model in pdb.models().skip(1) {
if model.atom_count() != total_atoms {
errors.push(PDBError::new(
ErrorLevel::StrictWarning,
"Invalid Model",
&format!(
"Model {} does not have the same amount of atoms as the first model.",
model.serial_number()
),
Context::None,
));
continue;
}
if model.total_atom_count() - model.atom_count() != total_hetero_atoms {
errors.push(PDBError::new(
ErrorLevel::LooseWarning,
"Invalid Model",
&format!(
"Model {} does not have the same amount of HETATMs as the first model.",
model.serial_number()
),
Context::None,
));
continue;
}
for index in 0..model.atom_count() {
let current_atom = model.atom(index).unwrap();
let standard_atom = pdb.model(0).unwrap().atom(index).unwrap();
if !standard_atom.corresponds(current_atom) {
errors.push(PDBError::new(
ErrorLevel::StrictWarning,
"Atoms in Models not corresponding",
&format!(
"Atom {} in Model {} does not correspond to the respective Atom in the first model.",
current_atom.serial_number(),
model.serial_number()
),
Context::None,
));
}
}
for offset in 0..model.total_atom_count() - model.atom_count() {
let index = model.atom_count() + offset;
let current_atom = model.atom(index).unwrap();
let standard_atom = pdb.model(0).unwrap().atom(index).unwrap();
if !standard_atom.corresponds(current_atom) {
errors.push(PDBError::new(
ErrorLevel::LooseWarning,
"HETATMs in Models not corresponding",
&format!(
"HETATM {} in Model {} does not correspond to the respective Atom in the first model.",
current_atom.serial_number(),
model.serial_number()
),
Context::None,
));
}
}
}
errors
}