molframe_core/contract/policy/
profile.rs1use super::fields::{
8 AlignmentPolicy, AltlocPolicy, AssemblyChoice, ContactDefinition, EquivalencePolicy,
9 HydrogenPolicy, MissingPolicy, ModelChoice, Namespace, PeriodicPolicy, Precision, ProfileId,
10 RadiiSet, SymmetryPolicy, Tolerance,
11};
12use super::fingerprint::{Fingerprint, Fnv1a};
13use std::fmt;
14use std::hash::{Hash, Hasher};
15
16#[derive(Clone, PartialEq, Debug, Default)]
32pub struct AnalysisPolicy {
33 pub assembly: AssemblyChoice,
35 pub model: ModelChoice,
37 pub altloc: AltlocPolicy,
39 pub identifiers: Namespace,
41 pub missing_atoms: MissingPolicy,
43 pub hydrogens: HydrogenPolicy,
45 pub atom_equivalence: EquivalencePolicy,
47 pub symmetry: SymmetryPolicy,
49 pub alignment: AlignmentPolicy,
51 pub precision: Precision,
53 pub periodic: PeriodicPolicy,
55 pub vdw_radii: RadiiSet,
57 pub contact_def: ContactDefinition,
59 pub float_tolerance: Tolerance,
61}
62
63impl AnalysisPolicy {
64 #[must_use]
69 pub fn profile(&self) -> Option<ProfileId> {
70 (*self == Self::default()).then_some(ProfileId::DEFAULT)
71 }
72
73 #[must_use]
79 pub fn fingerprint(&self) -> Fingerprint {
80 let mut hasher = Fnv1a::new();
81 self.assembly.hash(&mut hasher);
82 self.model.hash(&mut hasher);
83 self.altloc.hash(&mut hasher);
84 self.identifiers.hash(&mut hasher);
85 self.missing_atoms.hash(&mut hasher);
86 self.hydrogens.hash(&mut hasher);
87 self.atom_equivalence.hash(&mut hasher);
88 self.symmetry.hash(&mut hasher);
89 self.alignment.hash(&mut hasher);
90 self.precision.hash(&mut hasher);
91 self.periodic.hash(&mut hasher);
92 self.vdw_radii.hash(&mut hasher);
93 match self.contact_def {
94 ContactDefinition::DistanceCutoff { tolerance } => {
95 (0u8, tolerance.to_bits()).hash(&mut hasher);
96 }
97 ContactDefinition::SurfaceBased { probe } => {
98 (1u8, probe.to_bits()).hash(&mut hasher);
99 }
100 }
101 (
102 self.float_tolerance.relative.to_bits(),
103 self.float_tolerance.absolute.to_bits(),
104 )
105 .hash(&mut hasher);
106 Fingerprint::from_hash(hasher.finish())
107 }
108
109 #[must_use]
111 pub fn with_identifiers(mut self, namespace: Namespace) -> Self {
112 self.identifiers = namespace;
113 self
114 }
115
116 #[must_use]
118 pub fn with_altloc(mut self, altloc: AltlocPolicy) -> Self {
119 self.altloc = altloc;
120 self
121 }
122
123 #[must_use]
125 pub fn with_model(mut self, model: ModelChoice) -> Self {
126 self.model = model;
127 self
128 }
129
130 #[must_use]
132 pub fn with_assembly(mut self, assembly: AssemblyChoice) -> Self {
133 self.assembly = assembly;
134 self
135 }
136
137 #[must_use]
139 pub fn with_missing_atoms(mut self, missing: MissingPolicy) -> Self {
140 self.missing_atoms = missing;
141 self
142 }
143}
144
145impl fmt::Display for AnalysisPolicy {
146 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
149 match self.profile() {
150 Some(profile) => writeln!(f, "{profile}")?,
151 None => writeln!(f, "(modified from {})", ProfileId::DEFAULT)?,
152 }
153 writeln!(f, " assembly = {:?}", self.assembly)?;
154 writeln!(f, " model = {:?}", self.model)?;
155 writeln!(f, " altloc = {:?}", self.altloc)?;
156 writeln!(f, " identifiers = {:?}", self.identifiers)?;
157 writeln!(f, " missing_atoms = {:?}", self.missing_atoms)?;
158 writeln!(f, " hydrogens = {:?}", self.hydrogens)?;
159 writeln!(f, " atom_equivalence = {:?}", self.atom_equivalence)?;
160 writeln!(f, " symmetry = {:?}", self.symmetry)?;
161 writeln!(f, " alignment = {:?}", self.alignment)?;
162 writeln!(f, " precision = {:?}", self.precision)?;
163 writeln!(f, " periodic = {:?}", self.periodic)?;
164 writeln!(f, " vdw_radii = {:?}", self.vdw_radii)?;
165 writeln!(f, " contact_def = {:?}", self.contact_def)?;
166 write!(f, " float_tolerance = {:?}", self.float_tolerance)
167 }
168}
169
170#[cfg(test)]
171#[path = "profile_tests.rs"]
172mod tests;