Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion actions/generate_recipe.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@
"git",
"make",
"libtool",
"pybind11",
"sysroot_linux-64",
}

Expand Down
17 changes: 7 additions & 10 deletions doc/source/acknowledgements.rst
Original file line number Diff line number Diff line change
Expand Up @@ -421,17 +421,14 @@ for parsing mmCIF files. This is used under the terms of the MIT
or Boost Software License (the version bundled with gemmi is MIT,
while the version on GitHub is BSL)

pyboost11
---------
zpp::serializer
---------------

Thanks to Yung-Yu's excellent
`blog post <https://yyc.solvcon.net/en/latest/writing/2021/pyboost11/pyboost11.html>`__
on how to interconvert between boost::python and pybind11, and for providing
`pyboost11.hpp <https://yyc.solvcon.net/en/latest/writing/2021/pyboost11/code.html#pyboost11-code-pyboost11-hpp>`__
as a header-only library to support interconversion. This was really useful
to let me mix pybind11-wrapped gemmi objects with boost::python-wrapped sire.
The code is used under the terms of the liberal open source license
given at the top of the header file.
:mod:`sire` bundles the header-only
`zpp::serializer <https://github.com/eyalz800/serializer>`__ library (the
copy distributed with gemmi) to exchange gemmi structures with the gemmi
Python module using gemmi's own binary serialization. This is used under
the terms of the MIT license.

RDKit
-----
Expand Down
13 changes: 6 additions & 7 deletions pixi.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ platforms = ["linux-64", "linux-aarch64", "osx-arm64", "win-64"]
python = "*"
cmake = ">=3.30.0"
git = "*"
pybind11 = "*"
gsl = "*"
libboost-devel = "*"
libboost-python-devel = "*"
Expand All @@ -30,7 +29,7 @@ make = "*"
libtool = "*"
sysroot_linux-64 = "==2.17"
kartograf = ">=1.0.0"
gemmi = ">=0.6.4,<0.7.0"
gemmi = ">=0.7.0,<0.8.0"

# Host dependencies for local source builds (not used by generate_recipe.py)
[target.linux-64.host-dependencies]
Expand All @@ -51,14 +50,14 @@ cxx-compiler = "*"
make = "*"
libtool = "*"
kartograf = ">=1.0.0"
gemmi = ">=0.6.4,<0.7.0"
gemmi = ">=0.7.0,<0.8.0"

[target.osx-arm64.host-dependencies]
c-compiler = "*"
cxx-compiler = "*"

[target.win-64.dependencies]
gemmi = ">=0.6.4,<0.7.0"
gemmi = ">=0.7.0,<0.8.0"

[target.win-64.host-dependencies]
c-compiler = "*"
Expand Down Expand Up @@ -164,17 +163,17 @@ rdkit = ">=2023.0.0"

[feature.test.target.linux-64.dependencies]
kartograf = ">=1.0.0"
gemmi = ">=0.6.4,<0.7.0"
gemmi = ">=0.7.0,<0.8.0"

[feature.test.target.linux-aarch64.dependencies]
kartograf = ">=1.0.0"

[feature.test.target.osx-arm64.dependencies]
kartograf = ">=1.0.0"
gemmi = ">=0.6.4,<0.7.0"
gemmi = ">=0.7.0,<0.8.0"

[feature.test.target.win-64.dependencies]
gemmi = ">=0.6.4,<0.7.0"
gemmi = ">=0.7.0,<0.8.0"

# kartograf excluded from Windows test deps

Expand Down
3 changes: 1 addition & 2 deletions wrapper/Convert/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@ set( CMAKE_CXX_FLAGS "${OPTIMISED_CXX_FLAGS}" )

add_subdirectory (SireRDKit)
add_subdirectory (SireOpenMM)
# SireGemmi currently disabled due to build issues
# add_subdirectory (SireGemmi)
add_subdirectory (SireGemmi)

# installation
set( INSTALLDIR ${SIRE_PYTHON}/sire/legacy/Convert )
Expand Down
9 changes: 2 additions & 7 deletions wrapper/Convert/SireGemmi/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,19 @@
#
##########################################

# Find gemmi and pybind11 libraries
# Find gemmi library
find_package(gemmi)
find_package(pybind11)

if (${gemmi_FOUND} AND ${pybind11_FOUND})
if (${gemmi_FOUND})
# Only compile and install if we have gemmi
message( STATUS "Compiling SireGemmi converter" )

get_target_property(GEMMI_LOCATION gemmi::gemmi_cpp IMPORTED_LOCATION_RELEASE)
message( STATUS "gemmi location: ${GEMMI_LOCATION}" )
message( STATUS "PYBIND11 INCLUDE ${pybind11_INCLUDE_DIR}")
message( STATUS "PYBIND11 LIBRARY ${pybind11_LIBRARIES}" )
message( STATUS "ZLIB LIBRARIES ${ZLIB_LIBRARIES}" )

# Third Party dependencies of this module
include_directories( ${PYTHON_INCLUDE_DIR}
${pybind11_INCLUDE_DIR}
${gemmi_INCLUDE_DIR} )

# Sire include paths
Expand Down Expand Up @@ -59,7 +55,6 @@ if (${gemmi_FOUND} AND ${pybind11_FOUND})
SIRE_SireStream
SIRE_SireError
gemmi::gemmi_cpp
${pybind11_LIBRARIES}
)

include( LimitSirePythonExportSymbols )
Expand Down
42 changes: 30 additions & 12 deletions wrapper/Convert/SireGemmi/_SireGemmi.main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,33 +2,51 @@
// (C) Christopher Woods, GPL >= 3 License

#include "boost/python.hpp"
#include "boost/python/converter/registry.hpp"

#include "sire_gemmi.h"

#include "Helpers/pyboost11.hpp"
#include <gemmi/version.hpp>

namespace bp = boost::python;

using namespace SireGemmi;

#include <gemmi/model.hpp>
bp::object sire_to_gemmi_state_py(const SireSystem::System &system,
const SireBase::PropertyMap &map)
{
const auto state = sire_to_gemmi_state(system, map);

return bp::object(bp::handle<>(
PyBytes_FromStringAndSize(state.data(), state.size())));
}

SireSystem::System gemmi_state_to_sire_py(const bp::object &state,
const SireBase::PropertyMap &map)
{
char *data = nullptr;
Py_ssize_t size = 0;

if (PyBytes_AsStringAndSize(state.ptr(), &data, &size) != 0)
bp::throw_error_already_set();

return gemmi_state_to_sire(std::string(data, size), map);
}

BOOST_PYTHON_MODULE(_SireGemmi)
{
bp::def("sire_to_gemmi",
&sire_to_gemmi,
bp::def("_sire_to_gemmi_state",
&sire_to_gemmi_state_py,
(bp::arg("mols"), bp::arg("map")),
"Convert sire system to a gemmi structure");
"Convert sire system to the pickle state of a gemmi Structure");

bp::def("gemmi_to_sire",
&gemmi_to_sire,
(bp::arg("mols"), bp::arg("map")),
"Convert a gemmi Structure to a sire system");
bp::def("_gemmi_state_to_sire",
&gemmi_state_to_sire_py,
(bp::arg("state"), bp::arg("map")),
"Convert the pickle state of a gemmi Structure to a sire system");

bp::scope().attr("_gemmi_version") = GEMMI_VERSION;

bp::def("_register_pdbx_loader",
&register_pdbx_loader,
"Internal function called once used to register PDBx support");

pyboost11::converter<gemmi::Structure>();
}
45 changes: 37 additions & 8 deletions wrapper/Convert/SireGemmi/sire_gemmi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,29 @@
#include "sire_gemmi.h"

#include "gemmi/cif.hpp"
#include "gemmi/mmcif.hpp"
#include "gemmi/modify.hpp"
#include "gemmi/polyheur.hpp"
#include "gemmi/read_cif.hpp"
#include "gemmi/to_cif.hpp"
#include "gemmi/to_mmcif.hpp"
#include "gemmi/mmcif.hpp"

// gemmi/serialize.hpp requires the zpp serializer to be included first
#include "gemmi/serialize.hpp"
#include "third_party/serializer.h"

#include "SireIO/pdbx.h"

#include "SireMol/core.h"
#include "SireMol/moleditor.h"
#include "SireMol/element.h"
#include "SireMol/moleditor.h"

#include "SireMol/atomproperty.hpp"
#include "SireMol/atomelements.h"
#include "SireMol/atomcoords.h"
#include "SireMol/atomcharges.h"
#include "SireMol/connectivity.h"
#include "SireMol/atomcoords.h"
#include "SireMol/atomelements.h"
#include "SireMol/atomproperty.hpp"
#include "SireMol/bondhunter.h"
#include "SireMol/connectivity.h"

#include "SireMol/iswater.h"

Expand All @@ -30,9 +35,9 @@

#include "SireError/errors.h"

#include <string>
#include <sstream>
#include <iostream>
#include <sstream>
#include <string>

namespace cif = gemmi::cif;

Expand Down Expand Up @@ -1265,6 +1270,30 @@ namespace SireGemmi
return lines;
}

SireSystem::System gemmi_state_to_sire(const std::string &state,
const SireBase::PropertyMap &map)
{
gemmi::Structure structure;

zpp::serializer::memory_view_input_archive in(
reinterpret_cast<const unsigned char *>(state.data()), state.size());
in(structure);

return gemmi_to_sire(structure, map);
}

std::string sire_to_gemmi_state(const SireSystem::System &system,
const SireBase::PropertyMap &map)
{
const auto structure = sire_to_gemmi(system, map);

std::vector<unsigned char> data;
zpp::serializer::memory_output_archive out(data);
out(structure);

return std::string(data.begin(), data.end());
}

void register_pdbx_loader()
{
SireIO::PDBxReaderFunction reader_function(&pdbx_reader_function);
Expand Down
8 changes: 8 additions & 0 deletions wrapper/Convert/SireGemmi/sire_gemmi.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ namespace gemmi
#include "SireBase/propertymap.h"

#include <memory>
#include <string>

namespace SireGemmi
{
Expand All @@ -21,6 +22,13 @@ namespace SireGemmi
gemmi::Structure sire_to_gemmi(const SireSystem::System &system,
const SireBase::PropertyMap &map);

// Structures cross to Python as gemmi's pickle state (zpp serialized)
SireSystem::System gemmi_state_to_sire(const std::string &state,
const SireBase::PropertyMap &map);

std::string sire_to_gemmi_state(const SireSystem::System &system,
const SireBase::PropertyMap &map);

void register_pdbx_loader();
}

Expand Down
21 changes: 21 additions & 0 deletions wrapper/Convert/SireGemmi/third_party/LICENSE.zpp_serializer
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2019 Eyal Z

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
Loading