// SPDX-FileCopyrightText: 2026 Filip Leonarski, Paul Scherrer Institute // SPDX-License-Identifier: GPL-3.0-only #include "WriteModel.h" #include #include // make_mmcif_document #include // write_cif_to_stream #include // setup_entities #include "../common/Logger.h" void WritePlacedModel(const gemmi::Structure &placed, const UnitCell &cell, const gemmi::SpaceGroup &space_group, const std::string &output_prefix, Logger &logger) { const std::string path = output_prefix + "_model.cif"; gemmi::Structure st = placed; // Not the model's own cell and group but the data's, taken from the same two values the reflection // files are written from. The coordinates already sit in this cell; what is set here is the label // the file carries, which must match the .mtz beside it - the enantiomorph in particular, since // --model can adopt the model's and that is neither the data's original label nor, necessarily, // the one the input model arrived with. st.cell = cell; st.spacegroup_hm = space_group.xhm(); st.setup_cell_images(); // Fills in entity types and label_asym_id for a model read from a PDB, which carries neither. // Both are no-ops where the input already had them, i.e. for an mmCIF input. // setup_entities and make_mmcif_document can both throw, and this runs BEFORE the reflection files // are written: a convenience deliverable must not be able to take the run's actual output with it. // The map writer does the same. try { gemmi::setup_entities(st); std::ofstream os(path); gemmi::cif::write_cif_to_stream(os, gemmi::make_mmcif_document(st)); if (!os) { logger.Error("Model validation: cannot write the placed model to {}", path); return; } } catch (const std::exception &e) { logger.Warning("Model validation: could not write the placed model to {} ({})", path, e.what()); return; } logger.Info("Model validation: the model as placed against these data written to {} " "(cell and space group {} as in the reflection files)", path, space_group.short_name()); }