// Copyright 2018 Global Phasing Ltd. #include "gemmi/chemcomp.hpp" #include "gemmi/gzread.hpp" // for read_cif_gz #include "gemmi/monlib.hpp" #include "gemmi/placeh.hpp" // for adjust_hydrogen_distances #include "gemmi/topo.hpp" #include "gemmi/tostr.hpp" #include "common.h" #include #include namespace py = pybind11; using namespace gemmi; PYBIND11_MAKE_OPAQUE(std::vector) PYBIND11_MAKE_OPAQUE(std::vector) PYBIND11_MAKE_OPAQUE(std::vector) PYBIND11_MAKE_OPAQUE(std::vector) using monomers_type = std::map; using links_type = std::map; using modifications_type = std::map; PYBIND11_MAKE_OPAQUE(monomers_type) PYBIND11_MAKE_OPAQUE(links_type) PYBIND11_MAKE_OPAQUE(modifications_type) void add_monlib(py::module& m) { py::class_ chemmod(m, "ChemMod"); py::class_ chemlink(m, "ChemLink"); py::class_ chemlinkside(chemlink, "Side"); py::class_ chemcomp(m, "ChemComp"); py::class_ chemcompatom(chemcomp, "Atom"); py::class_ restraints(m, "Restraints"); py::class_ restraintsbond(restraints, "Bond"); py::class_ topo(m, "Topo"); py::class_ topobond(topo, "Bond"); py::class_ topoextralink(topo, "ExtraLink"); py::bind_vector>(m, "RestraintsBonds"); py::bind_vector>(m, "ChemCompAtoms"); py::bind_vector>(m, "TopoBonds"); py::bind_vector>(m, "TopoExtraLinks"); py::bind_map(m, "ChemCompMap"); py::bind_map(m, "ChemLinkMap"); py::bind_map(m, "ChemModMap"); py::enum_(m, "BondType") .value("Unspec", BondType::Unspec) .value("Single", BondType::Single) .value("Double", BondType::Double) .value("Triple", BondType::Triple) .value("Aromatic", BondType::Aromatic) .value("Deloc", BondType::Deloc) .value("Metal", BondType::Metal); py::enum_(m, "HydrogenChange") .value("None", HydrogenChange::None) .value("Shift", HydrogenChange::Shift) .value("Remove", HydrogenChange::Remove) .value("ReAdd", HydrogenChange::ReAdd) .value("ReAddButWater", HydrogenChange::ReAddButWater); py::enum_(restraints, "DistanceOf") .value("ElectronCloud", Restraints::DistanceOf::ElectronCloud) .value("Nucleus", Restraints::DistanceOf::Nucleus); py::class_(restraints, "AtomId") .def(py::init([](int comp, const std::string& atom) { return new Restraints::AtomId{comp, atom}; })) .def(py::init([](const std::string& atom) { return new Restraints::AtomId{1, atom}; })) .def_readwrite("comp", &Restraints::AtomId::comp) .def_readwrite("atom", &Restraints::AtomId::atom) .def("get_from", (Atom* (Restraints::AtomId::*)(Residue&, Residue*, char) const) &Restraints::AtomId::get_from, py::arg("res1"), py::arg("res2"), py::arg("altloc"), py::return_value_policy::reference) .def("__repr__", [](const Restraints::AtomId& self) { return tostr("'); }); restraintsbond .def_readwrite("id1", &Restraints::Bond::id1) .def_readwrite("id2", &Restraints::Bond::id2) .def_readwrite("type", &Restraints::Bond::type) .def_readwrite("aromatic", &Restraints::Bond::aromatic) .def_readwrite("value", &Restraints::Bond::value) .def_readwrite("esd", &Restraints::Bond::esd) .def_readwrite("value_nucleus", &Restraints::Bond::value_nucleus) .def("lexicographic_str", &Restraints::Bond::lexicographic_str) .def("__repr__", [](const Restraints::Bond& self) { return ""; }); restraints .def_readwrite("bonds", &Restraints::bonds) .def("empty", &Restraints::empty) .def("get_bond", &Restraints::get_bond, py::return_value_policy::reference_internal) .def("get_bond", [](Restraints& self, const std::string& a1, const std::string& a2) -> Restraints::Bond& { auto it = self.find_bond(a1, a2); if (it == self.bonds.end()) fail("Bond restraint not found: " + a1 + "-" + a2); return *it; }, py::return_value_policy::reference_internal) .def("find_shortest_path", &Restraints::find_shortest_path) ; chemcompatom .def_readonly("id", &ChemComp::Atom::id) .def_readonly("el", &ChemComp::Atom::el) .def_readonly("charge", &ChemComp::Atom::charge) .def_readonly("chem_type", &ChemComp::Atom::chem_type) .def("is_hydrogen", &ChemComp::Atom::is_hydrogen) ; chemcomp .def_readonly("name", &ChemComp::name) .def_readonly("group", &ChemComp::group) .def_readonly("atoms", &ChemComp::atoms) .def_readonly("rt", &ChemComp::rt) .def("get_atom", &ChemComp::get_atom) .def("remove_hydrogens", &ChemComp::remove_hydrogens) ; m.def("make_chemcomp_from_block", &make_chemcomp_from_block); chemlink .def_readwrite("id", &ChemLink::id) .def_readwrite("name", &ChemLink::name) .def_readwrite("side1", &ChemLink::side1) .def_readwrite("side2", &ChemLink::side2) .def_readwrite("rt", &ChemLink::rt) .def("__repr__", [](const ChemLink& self) { return ""; }); py::enum_(chemlinkside, "Group") .value("Peptide", ChemLink::Group::Peptide) .value("PPeptide", ChemLink::Group::PPeptide) .value("MPeptide", ChemLink::Group::MPeptide) .value("Pyranose", ChemLink::Group::Pyranose) .value("DnaRna", ChemLink::Group::DnaRna) .value("Null", ChemLink::Group::Null); chemlinkside .def_readwrite("comp", &ChemLink::Side::comp) .def_readwrite("mod", &ChemLink::Side::mod) .def_readwrite("group", &ChemLink::Side::group) .def("__repr__", [](const ChemLink::Side& self) { return ""; }); chemmod .def_readwrite("id", &ChemMod::id) .def("__repr__", [](const ChemLink& self) { return ""; }); py::class_(m, "MonLib") .def(py::init<>()) .def_readonly("monomers", &MonLib::monomers) .def_readonly("links", &MonLib::links) .def_readonly("modifications", &MonLib::modifications) .def("find_link", &MonLib::find_link, py::arg("link_id"), py::return_value_policy::reference_internal) .def("add_monomer_if_present", &MonLib::add_monomer_if_present) .def("add_monomers_if_present", &MonLib::add_monomers_if_present) .def("__repr__", [](const MonLib& self) { return ""; }); topobond .def_readonly("restr", &Topo::Bond::restr) .def_readonly("atoms", &Topo::Bond::atoms) .def("calculate", &Topo::Bond::calculate) .def("calculate_z", &Topo::Bond::calculate_z) ; topoextralink .def_readonly("res1", &Topo::ExtraLink::res1) .def_readonly("res2", &Topo::ExtraLink::res2) .def_readonly("alt1", &Topo::ExtraLink::alt1) .def_readonly("alt2", &Topo::ExtraLink::alt2) .def_readonly("link_id", &Topo::ExtraLink::link_id) ; topo .def(py::init<>()) .def("adjust_hydrogen_distances", &adjust_hydrogen_distances) .def_readonly("bonds", &Topo::bonds) .def_readonly("extras", &Topo::extras) ; m.def("prepare_topology", &prepare_topology, py::arg("st"), py::arg("monlib"), py::arg("model_index")=0, py::arg("h_change")=HydrogenChange::None, py::arg("reorder")=false, py::arg("raise_errors")=false); m.def("read_monomer_lib", [](const std::string& monomer_dir, const std::vector& resnames) { return read_monomer_lib(monomer_dir, resnames, gemmi::read_cif_gz); }); m.def("read_monomer_cif", [](const std::string& path) { return read_monomer_cif(path, gemmi::read_cif_gz); }); py::class_(m, "BondIndex") .def(py::init(), py::keep_alive<1, 2>()) .def("add_link", &BondIndex::add_link) .def("add_monomer_bonds", &BondIndex::add_monomer_bonds) .def("are_linked", &BondIndex::are_linked) .def("graph_distance", &BondIndex::graph_distance, py::arg("a"), py::arg("b"), py::arg("same_index"), py::arg("max_distance")=4) ; }