use molframe_core::structure::Structure;
#[cfg(feature = "crystal")]
pub(crate) fn complete(
structure: &Structure,
options: &molframe_pdb::PdbOptions,
) -> molframe_pdb::PdbOptions {
let mut completed = options.clone();
{
let extensions = structure.extensions();
if structure.data().entry.space_group.is_none()
&& let Some(symbol) = extensions
.get::<molframe_xtal::SymmetrySet>(molframe_xtal::SYMMETRY_EXTENSION)
.and_then(|set| set.hermann_mauguin.as_deref())
{
completed = completed.with_space_group(symbol);
}
if completed.extra_records().is_none()
&& let Some(set) = extensions.get::<molframe_xtal::NcsSet>(molframe_xtal::NCS_EXTENSION)
{
let text = mtrix_records(set);
if !text.is_empty() {
completed = completed.with_extra_records(text);
}
}
}
completed
}
#[cfg(not(feature = "crystal"))]
pub(crate) fn complete(
_structure: &Structure,
options: &molframe_pdb::PdbOptions,
) -> molframe_pdb::PdbOptions {
options.clone()
}
#[cfg(feature = "crystal")]
fn mtrix_records(set: &molframe_xtal::NcsSet) -> String {
use std::fmt::Write as _;
let mut out = String::new();
let numeric: Option<Vec<u32>> = set
.operators()
.map(|operator| operator.id.parse().ok())
.collect();
let mut ordered: Vec<(u32, &molframe_xtal::NcsOperator)> = set
.operators()
.enumerate()
.map(|(position, operator)| {
let recorded = numeric.as_ref().and_then(|ids| ids.get(position).copied());
let id = match recorded {
Some(id) => id,
None => molframe_core::numeric::usize_to_u32(position + 1),
};
(id, operator)
})
.collect();
ordered.sort_by_key(|(serial, _)| *serial);
for (serial, operator) in ordered {
let transform = &operator.transform;
let given = if operator.code == molframe_xtal::NcsCode::Given {
'1'
} else {
' '
};
for row in 0..3 {
let _ = writeln!(
out,
"MTRIX{} {:>3}{:10.6}{:10.6}{:10.6} {:10.5} {}",
row + 1,
serial,
transform.matrix[row][0],
transform.matrix[row][1],
transform.matrix[row][2],
transform.translation[row],
given,
);
}
}
out
}