Skip to main content

molframe_core/structure/
label_rewrites.rs

1//! What [`Structure::with_distinct_labels`] changes, for a writer to report.
2//!
3//! The distinct view is silent by construction; a writer that projects it owes
4//! its caller the list of identifiers it rewrote, so the rewrite never reads as
5//! the depositor's own naming.
6
7use super::Structure;
8
9/// The normalised identifiers a distinct-label view rewrites.
10#[derive(Clone, Debug, Default, PartialEq, Eq)]
11pub struct LabelRewrites {
12    /// Each renamed chain as `(original label, new label)`.
13    pub chains: Vec<(String, String)>,
14    /// How many residues took a shifted normalised sequence number.
15    pub residues: usize,
16}
17
18impl LabelRewrites {
19    /// Whether the view changes nothing.
20    #[must_use]
21    pub fn is_empty(&self) -> bool {
22        self.chains.is_empty() && self.residues == 0
23    }
24}
25
26impl Structure {
27    /// The rewrites [`Structure::with_distinct_labels`] would make, in the
28    /// first model's topology.
29    #[must_use]
30    pub fn label_rewrites(&self) -> LabelRewrites {
31        let Some(distinct) = self.with_distinct_labels() else {
32            return LabelRewrites::default();
33        };
34        let chains = self
35            .data()
36            .chains()
37            .zip(distinct.data().chains())
38            .filter_map(|(before, after)| {
39                let (before, after) = (before.label()?, after.label()?);
40                (before != after).then(|| (before.to_owned(), after.to_owned()))
41            })
42            .collect();
43        let residues = self
44            .data()
45            .residues()
46            .zip(distinct.data().residues())
47            .filter(|(before, after)| before.label_seq_id() != after.label_seq_id())
48            .count();
49        LabelRewrites { chains, residues }
50    }
51}
52
53#[cfg(test)]
54#[path = "label_rewrites_tests.rs"]
55mod tests;