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
//! What [`Structure::with_distinct_labels`] changes, for a writer to report.
//!
//! The distinct view is silent by construction; a writer that projects it owes
//! its caller the list of identifiers it rewrote, so the rewrite never reads as
//! the depositor's own naming.
use super::Structure;
/// The normalised identifiers a distinct-label view rewrites.
#[derive(Clone, Debug, Default, PartialEq, Eq)]
pub struct LabelRewrites {
/// Each renamed chain as `(original label, new label)`.
pub chains: Vec<(String, String)>,
/// How many residues took a shifted normalised sequence number.
pub residues: usize,
}
impl LabelRewrites {
/// Whether the view changes nothing.
#[must_use]
pub fn is_empty(&self) -> bool {
self.chains.is_empty() && self.residues == 0
}
}
impl Structure {
/// The rewrites [`Structure::with_distinct_labels`] would make, in the
/// first model's topology.
#[must_use]
pub fn label_rewrites(&self) -> LabelRewrites {
let Some(distinct) = self.with_distinct_labels() else {
return LabelRewrites::default();
};
let chains = self
.data()
.chains()
.zip(distinct.data().chains())
.filter_map(|(before, after)| {
let (before, after) = (before.label()?, after.label()?);
(before != after).then(|| (before.to_owned(), after.to_owned()))
})
.collect();
let residues = self
.data()
.residues()
.zip(distinct.data().residues())
.filter(|(before, after)| before.label_seq_id() != after.label_seq_id())
.count();
LabelRewrites { chains, residues }
}
}
#[cfg(test)]
#[path = "label_rewrites_tests.rs"]
mod tests;