Commit 31c86d9c by Maarten L. Hekkelman

stripped to remove dependency on clipper and CCP4

parent 85b08f9d
...@@ -30,7 +30,8 @@ firstTarget: all ...@@ -30,7 +30,8 @@ firstTarget: all
CXX = @CXX@ CXX = @CXX@
CXXFLAGS = @CXXFLAGS@ @BOOST_CPPFLAGS@ @LIBBZ2_CPPFLAGS@ CXXFLAGS = @CXXFLAGS@ @BOOST_CPPFLAGS@ @LIBBZ2_CPPFLAGS@
LDFLAGS = @LDFLAGS@ @LIBS@ @BOOST_LDFLAGS@ @LIBBZ2_LDFLAGS@ LDFLAGS = @LDFLAGS@ @LIBS@ @BOOST_LDFLAGS@ @LIBBZ2_LDFLAGS@
LIBS = @LIBS@ LIBS = @BOOST_IOSTREAMS_LIB@ \
@LIBS@
prefix = @prefix@ prefix = @prefix@
exec_prefix = @exec_prefix@ exec_prefix = @exec_prefix@
...@@ -89,24 +90,18 @@ endif ...@@ -89,24 +90,18 @@ endif
$(OBJDIR): $(OBJDIR):
mkdir -p $(OBJDIR) mkdir -p $(OBJDIR)
LIBCIF_SRC = AtomShape.cpp \ LIBCIF_SRC = AtomType.cpp \
AtomType.cpp \
BondMap.cpp \
Cif2PDB.cpp \ Cif2PDB.cpp \
Cif++.cpp \ Cif++.cpp \
CifParser.cpp \ CifParser.cpp \
CifUtils.cpp \ CifUtils.cpp \
CifValidator.cpp \ CifValidator.cpp \
Compound.cpp \ Compound.cpp \
DistanceMap.cpp \
FixDMC.cpp \ FixDMC.cpp \
MapMaker.cpp \
PDB2Cif.cpp \ PDB2Cif.cpp \
PDB2CifRemark3.cpp \ PDB2CifRemark3.cpp \
Point.cpp \ Point.cpp \
ResolutionCalculator.cpp \
Secondary.cpp \ Secondary.cpp \
Statistics.cpp \
Structure.cpp \ Structure.cpp \
Symmetry.cpp \ Symmetry.cpp \
TlsParser.cpp TlsParser.cpp
...@@ -170,10 +165,6 @@ distclean: clean ...@@ -170,10 +165,6 @@ distclean: clean
# Test rules # Test rules
BOOST_LIBS = iostreams thread filesystem timer chrono regex
CLIPPER_LIBS = core ccp4
CLIPPER_LIBS := $(CLIPPER_LIBS:%=-lclipper-%)
define TEST_template = define TEST_template =
-include $$(OBJDIR)/$(1)-test.d -include $$(OBJDIR)/$(1)-test.d
...@@ -182,7 +173,7 @@ $(1)_OBJECTS = $$(OBJDIR)/$(1)-test.o ...@@ -182,7 +173,7 @@ $(1)_OBJECTS = $$(OBJDIR)/$(1)-test.o
test/$(1)-test: $(LIB_TARGET) $$($(1)_OBJECTS) test/$(1)-test: $(LIB_TARGET) $$($(1)_OBJECTS)
@ echo ">>> building $(1)-test" @ echo ">>> building $(1)-test"
$(LIBTOOL) --silent --tag=CXX --mode=link $(CXX) $(CXXFLAGS) $(LDFLAGS) -o $$@ $$($(1)_OBJECTS) -L.libs -Wl,-rpath /srv/ccp4-7.1/lib -lbz2 -lz -lcif++ $(CLIPPER_LIBS) $(BOOST_LIBS:%=-lboost_%) $(LIBS) -lstdc++fs $(LIBTOOL) --silent --tag=CXX --mode=link $(CXX) $(CXXFLAGS) $(LDFLAGS) -o $$@ $$($(1)_OBJECTS) -L.libs -lboost_timer -lcif++ $(LIBS)
.PHONY: $(1)-test .PHONY: $(1)-test
$(1)-test: test/$(1)-test $(1)-test: test/$(1)-test
......
...@@ -6,7 +6,7 @@ AX_CXX_COMPILE_STDCXX_17([noext]) ...@@ -6,7 +6,7 @@ AX_CXX_COMPILE_STDCXX_17([noext])
AX_CHECK_COMPILE_FLAG([-fstandalone-debug], , , [-Werror]) AX_CHECK_COMPILE_FLAG([-fstandalone-debug], , , [-Werror])
AC_CONFIG_SRCDIR([src/AtomShape.cpp]) AC_CONFIG_SRCDIR([src/Cif++.cpp])
AC_CONFIG_AUX_DIR(config) AC_CONFIG_AUX_DIR(config)
AC_CONFIG_MACRO_DIR([config/m4]) AC_CONFIG_MACRO_DIR([config/m4])
AC_CONFIG_HEADERS([include/cif++/Config.hpp]) AC_CONFIG_HEADERS([include/cif++/Config.hpp])
...@@ -31,28 +31,16 @@ AC_CHECK_HEADERS([sys/ioctl.h]) ...@@ -31,28 +31,16 @@ AC_CHECK_HEADERS([sys/ioctl.h])
AC_CHECK_HEADERS([termios.h]) AC_CHECK_HEADERS([termios.h])
AC_CHECK_HEADER_STDBOOL AC_CHECK_HEADER_STDBOOL
AC_CHECK_TYPES([ptrdiff_t]) AC_CHECK_TYPES([ptrdiff_t])
AC_C_INLINE
AC_FUNC_ERROR_AT_LINE
AC_FUNC_MALLOC
AC_FUNC_STRTOD
AC_PROG_MAKE_SET AC_PROG_MAKE_SET
AC_TYPE_INT32_T
AC_TYPE_INT64_T # AC_ARG_VAR([CCP4], [The location where CCP4 is installed])
AC_TYPE_INT8_T
AC_TYPE_SIZE_T # AS_IF([test x"$CCP4" != x""],
AC_TYPE_UINT16_T # [
AC_TYPE_UINT32_T # CPPFLAGS="$CPPFLAGS -I ${CCP4}/include"
AC_TYPE_UINT64_T # CXXFLAGS="$CXXFLAGS -I ${CCP4}/include"
AC_TYPE_UINT8_T # LDFLAGS="$LDFLAGS -L${CCP4}/lib"
# ])
AC_ARG_VAR([CCP4], [The location where CCP4 is installed])
AS_IF([test x"$CCP4" != x""],
[
CPPFLAGS="$CPPFLAGS -I ${CCP4}/include"
CXXFLAGS="$CXXFLAGS -I ${CCP4}/include"
LDFLAGS="$LDFLAGS -L${CCP4}/lib"
])
AC_ARG_VAR([USE_RSRC], [Use resources to store internal data, requires mrc]) AC_ARG_VAR([USE_RSRC], [Use resources to store internal data, requires mrc])
AC_ARG_VAR([MRC], [Specify a location for the mrc executable]) AC_ARG_VAR([MRC], [Specify a location for the mrc executable])
...@@ -103,48 +91,48 @@ AX_BOOST_IOSTREAMS ...@@ -103,48 +91,48 @@ AX_BOOST_IOSTREAMS
dnl AX_BOOST_FILESYSTEM dnl AX_BOOST_FILESYSTEM
AX_BOOST_THREAD AX_BOOST_THREAD
AC_ARG_WITH([clipper], # AC_ARG_WITH([clipper],
AS_HELP_STRING([--with-clipper=@<:@location@:>@], # AS_HELP_STRING([--with-clipper=@<:@location@:>@],
[Use the clipper library as specified. # [Use the clipper library as specified.
@<:@location=$CCP4@:>@]), # @<:@location=$CCP4@:>@]),
[ # [
CPPFLAGS="$CPPFLAGS -I ${withval}/include" # CPPFLAGS="$CPPFLAGS -I ${withval}/include"
CXXFLAGS="$CXXFLAGS -I ${withval}/include" # CXXFLAGS="$CXXFLAGS -I ${withval}/include"
LDFLAGS="$LDFLAGS -L${withval}/lib" # LDFLAGS="$LDFLAGS -L${withval}/lib"
]) # ])
AC_ARG_WITH([newuoa], # AC_ARG_WITH([newuoa],
AS_HELP_STRING([--with-newuoa=@<:@location@:>@], # AS_HELP_STRING([--with-newuoa=@<:@location@:>@],
[Use the newuoa library as specified.]), # [Use the newuoa library as specified.]),
[ # [
CPPFLAGS="$CPPFLAGS -I ${withval}/include" # CPPFLAGS="$CPPFLAGS -I ${withval}/include"
CXXFLAGS="$CXXFLAGS -I ${withval}/include" # CXXFLAGS="$CXXFLAGS -I ${withval}/include"
LDFLAGS="$LDFLAGS -L${withval}/lib" # LDFLAGS="$LDFLAGS -L${withval}/lib"
]) # ])
AC_CHECK_HEADER( # AC_CHECK_HEADER(
[clipper/clipper.h], # [clipper/clipper.h],
[], # [],
[AC_MSG_ERROR([ # [AC_MSG_ERROR([
Can't find the main clipper include file clipper/clipper.h. Please # Can't find the main clipper include file clipper/clipper.h. Please
specify either the CCP4 location of the location of the installed # specify either the CCP4 location of the location of the installed
clipper using --with-clipper=<path> # clipper using --with-clipper=<path>
])]) # ])])
# AC_MSG_CHECKING([clipper version])
# AC_COMPILE_IFELSE(
# [read_test(clipper-test.cpp)],
# [],
# [AC_MSG_ERROR([The version of clipper is not up to date])])
AC_MSG_CHECKING([clipper version]) # AC_CHECK_HEADER(
AC_COMPILE_IFELSE( # [newuoa.h],
[read_test(clipper-test.cpp)], # [],
[], # [AC_MSG_ERROR([
[AC_MSG_ERROR([The version of clipper is not up to date])]) # Can't find the newuoa include file newuoa.h. Please install this
# library and specify its location with --with-newuoa=<path>.
AC_CHECK_HEADER( # You can find newuoa at https://github.com/elsid/newuoa-cpp.git
[newuoa.h], # ])])
[],
[AC_MSG_ERROR([
Can't find the newuoa include file newuoa.h. Please install this
library and specify its location with --with-newuoa=<path>.
You can find newuoa at https://github.com/elsid/newuoa-cpp.git
])])
AX_CHECK_LIBRARY([LIBZ], [zlib.h], [z], [], AX_CHECK_LIBRARY([LIBZ], [zlib.h], [z], [],
[AC_MSG_ERROR([libz not found - compressed files not supported])]) [AC_MSG_ERROR([libz not found - compressed files not supported])])
......
/*-
* SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2020 NKI/AVL, Netherlands Cancer Institute
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
// AtomShape, analogue to the similarly named code in clipper
#pragma once
#include "cif++/Structure.hpp"
namespace mmcif
{
// --------------------------------------------------------------------
// Class used in calculating radii
class AtomShape
{
public:
AtomShape(const Atom& atom, float resHigh, float resLow,
bool electronScattering);
AtomShape(const Atom& atom, float resHigh, float resLow,
bool electronScattering, float bFactor);
~AtomShape();
AtomShape(const AtomShape&) = delete;
AtomShape& operator=(const AtomShape&) = delete;
float radius() const;
float calculatedDensity(float r) const;
float calculatedDensity(Point p) const;
private:
struct AtomShapeImpl* mImpl;
};
}
...@@ -28,9 +28,11 @@ ...@@ -28,9 +28,11 @@
#pragma once #pragma once
#include "cif++/Config.hpp" #include <cstdint>
#include <string>
#include <stdexcept>
#include <boost/math/quaternion.hpp> #include "cif++/Config.hpp"
namespace mmcif namespace mmcif
{ {
......
/*-
* SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2020 NKI/AVL, Netherlands Cancer Institute
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#pragma once
#include <unordered_map>
#include "cif++/Structure.hpp"
namespace mmcif
{
class BondMap
{
public:
BondMap(const Structure& p);
BondMap(const BondMap&) = delete;
BondMap& operator=(const BondMap&) = delete;
bool operator()(const Atom& a, const Atom& b) const
{
return isBonded(index.at(a.id()), index.at(b.id()));
}
bool is1_4(const Atom& a, const Atom& b) const
{
uint32_t ixa = index.at(a.id());
uint32_t ixb = index.at(b.id());
return bond_1_4.count(key(ixa, ixb));
}
// links coming from the struct_conn records:
std::vector<std::string> linked(const Atom& a) const;
private:
bool isBonded(uint32_t ai, uint32_t bi) const
{
return bond.count(key(ai, bi)) != 0;
}
uint64_t key(uint32_t a, uint32_t b) const
{
if (a > b)
std::swap(a, b);
return static_cast<uint64_t>(a) | (static_cast<uint64_t>(b) << 32);
}
std::tuple<uint32_t,uint32_t> dekey(uint64_t k) const
{
return std::make_tuple(
static_cast<uint32_t>(k >> 32),
static_cast<uint32_t>(k)
);
}
uint32_t dim;
std::unordered_map<std::string,uint32_t> index;
std::set<uint64_t> bond, bond_1_4;
std::map<std::string,std::set<std::string>> link;
};
}
...@@ -33,7 +33,7 @@ void WritePDBFile(std::ostream& pdbFile, cif::File& cifFile); ...@@ -33,7 +33,7 @@ void WritePDBFile(std::ostream& pdbFile, cif::File& cifFile);
/// \brief Just the HEADER, COMPND, SOURCE and AUTHOR lines /// \brief Just the HEADER, COMPND, SOURCE and AUTHOR lines
void WritePDBHeaderLines(std::ostream& os, cif::File& cifFile); void WritePDBHeaderLines(std::ostream& os, cif::File& cifFile);
std::string GetPDBHEADERLine(cif::File& cifFile, int truncate_at = 127); std::string GetPDBHEADERLine(cif::File& cifFile, std::string::size_type truncate_at = 127);
std::string GetPDBCOMPNDLine(cif::File& cifFile, int truncate_at = 127); std::string GetPDBCOMPNDLine(cif::File& cifFile, std::string::size_type truncate_at = 127);
std::string GetPDBSOURCELine(cif::File& cifFile, int truncate_at = 127); std::string GetPDBSOURCELine(cif::File& cifFile, std::string::size_type truncate_at = 127);
std::string GetPDBAUTHORLine(cif::File& cifFile, int truncate_at = 127); std::string GetPDBAUTHORLine(cif::File& cifFile, std::string::size_type truncate_at = 127);
...@@ -24,6 +24,8 @@ ...@@ -24,6 +24,8 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#pragma once
#include "cif++/Cif++.hpp" #include "cif++/Cif++.hpp"
#include <stack> #include <stack>
...@@ -155,7 +157,7 @@ class SacParser ...@@ -155,7 +157,7 @@ class SacParser
virtual void produceDatablock(const std::string& name) = 0; virtual void produceDatablock(const std::string& name) = 0;
virtual void produceCategory(const std::string& name) = 0; virtual void produceCategory(const std::string& name) = 0;
virtual void produceRow() = 0; virtual void produceRow() = 0;
virtual void produceItem(const std::string& category, const std::string& item, const string& value) = 0; virtual void produceItem(const std::string& category, const std::string& item, const std::string& value) = 0;
protected: protected:
......
...@@ -31,6 +31,8 @@ ...@@ -31,6 +31,8 @@
#include <vector> #include <vector>
#include <set> #include <set>
#include <cassert> #include <cassert>
#include <memory>
#include <list>
#include <unistd.h> #include <unistd.h>
......
...@@ -24,6 +24,8 @@ ...@@ -24,6 +24,8 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#pragma once
#include "cif++/Cif++.hpp" #include "cif++/Cif++.hpp"
//// the std regex of gcc is crashing.... //// the std regex of gcc is crashing....
...@@ -113,11 +115,11 @@ struct ValidateItem ...@@ -113,11 +115,11 @@ struct ValidateItem
struct ValidateCategory struct ValidateCategory
{ {
std::string mName; std::string mName;
std::vector<string> mKeys; std::vector<std::string> mKeys;
cif::iset mGroups; cif::iset mGroups;
cif::iset mMandatoryFields; cif::iset mMandatoryFields;
std::set<ValidateItem> mItemValidators; std::set<ValidateItem> mItemValidators;
bool operator<(const ValidateCategory& rhs) const bool operator<(const ValidateCategory& rhs) const
{ {
......
/* include/cif++/Config.hpp. Generated from Config.hpp.in by configure. */
/*-
* SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2020 NKI/AVL, Netherlands Cancer Institute
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#pragma once
#if defined(_MSC_VER)
// These are Microsoft Visual C++ special settings
// the iso646 file contains the C++ keywords that are
// otherwise not recognized.
#include <ciso646>
#define snprintf _snprintf
// Disable some warnings
#pragma warning (disable : 4996)
#pragma warning (disable : 4355)
#endif
/* define if the Boost library is available */
#define HAVE_BOOST /**/
/* define if the Boost::IOStreams library is available */
#define HAVE_BOOST_IOSTREAMS /**/
/* define if the Boost::Regex library is available */
#define HAVE_BOOST_REGEX /**/
/* define if the Boost::Thread library is available */
#define HAVE_BOOST_THREAD /**/
/* define if the compiler supports basic C++17 syntax */
#define HAVE_CXX17 1
/* Define to 1 if you have the <dlfcn.h> header file. */
#define HAVE_DLFCN_H 1
/* Define to 1 if you have the `floor' function. */
#define HAVE_FLOOR 1
/* Define to 1 if you have the <inttypes.h> header file. */
#define HAVE_INTTYPES_H 1
/* Define to 1 if LIBBZ2 is found */
#define HAVE_LIBBZ2 1
/* Define to 1 if LIBZ is found */
#define HAVE_LIBZ 1
/* Define to 1 if your system has a GNU libc compatible `malloc' function, and
to 0 otherwise. */
/* #undef HAVE_MALLOC */
/* Define to 1 if you have the <memory.h> header file. */
#define HAVE_MEMORY_H 1
/* Define to 1 if you have the `pow' function. */
#define HAVE_POW 1
/* Define to 1 if the system has the type `ptrdiff_t'. */
#define HAVE_PTRDIFF_T 1
/* Define to 1 if you have the `rint' function. */
#define HAVE_RINT 1
/* Define to 1 if you have the `sqrt' function. */
#define HAVE_SQRT 1
/* Define to 1 if you have the <stdint.h> header file. */
#define HAVE_STDINT_H 1
/* Define to 1 if you have the <stdlib.h> header file. */
#define HAVE_STDLIB_H 1
/* Define to 1 if you have the `strchr' function. */
#define HAVE_STRCHR 1
/* Define to 1 if you have the `strerror' function. */
#define HAVE_STRERROR 1
/* Define to 1 if you have the <strings.h> header file. */
#define HAVE_STRINGS_H 1
/* Define to 1 if you have the <string.h> header file. */
#define HAVE_STRING_H 1
/* Define to 1 if you have the <sys/ioctl.h> header file. */
#define HAVE_SYS_IOCTL_H 1
/* Define to 1 if you have the <sys/stat.h> header file. */
#define HAVE_SYS_STAT_H 1
/* Define to 1 if you have the <sys/types.h> header file. */
#define HAVE_SYS_TYPES_H 1
/* Define to 1 if you have the <termios.h> header file. */
#define HAVE_TERMIOS_H 1
/* Define to 1 if you have the <unistd.h> header file. */
#define HAVE_UNISTD_H 1
/* Define to 1 if the system has the type `_Bool'. */
/* #undef HAVE__BOOL */
/* Define to the sub-directory where libtool stores uninstalled libraries. */
#define LT_OBJDIR ".libs/"
/* Define to 1 if you have the ANSI C header files. */
#define STDC_HEADERS 1
...@@ -129,58 +129,3 @@ ...@@ -129,58 +129,3 @@
/* Define to 1 if you have the ANSI C header files. */ /* Define to 1 if you have the ANSI C header files. */
#undef STDC_HEADERS #undef STDC_HEADERS
/* Define for Solaris 2.5.1 so the uint32_t typedef from <sys/synch.h>,
<pthread.h>, or <semaphore.h> is not used. If the typedef were allowed, the
#define below would cause a syntax error. */
#undef _UINT32_T
/* Define for Solaris 2.5.1 so the uint64_t typedef from <sys/synch.h>,
<pthread.h>, or <semaphore.h> is not used. If the typedef were allowed, the
#define below would cause a syntax error. */
#undef _UINT64_T
/* Define for Solaris 2.5.1 so the uint8_t typedef from <sys/synch.h>,
<pthread.h>, or <semaphore.h> is not used. If the typedef were allowed, the
#define below would cause a syntax error. */
#undef _UINT8_T
/* Define to `__inline__' or `__inline' if that's what the C compiler
calls it, or to nothing if 'inline' is not supported under any name. */
#ifndef __cplusplus
#undef inline
#endif
/* Define to the type of a signed integer type of width exactly 32 bits if
such a type exists and the standard includes do not define it. */
#undef int32_t
/* Define to the type of a signed integer type of width exactly 64 bits if
such a type exists and the standard includes do not define it. */
#undef int64_t
/* Define to the type of a signed integer type of width exactly 8 bits if such
a type exists and the standard includes do not define it. */
#undef int8_t
/* Define to rpl_malloc if the replacement function should be used. */
#undef malloc
/* Define to `unsigned int' if <sys/types.h> does not define. */
#undef size_t
/* Define to the type of an unsigned integer type of width exactly 16 bits if
such a type exists and the standard includes do not define it. */
#undef uint16_t
/* Define to the type of an unsigned integer type of width exactly 32 bits if
such a type exists and the standard includes do not define it. */
#undef uint32_t
/* Define to the type of an unsigned integer type of width exactly 64 bits if
such a type exists and the standard includes do not define it. */
#undef uint64_t
/* Define to the type of an unsigned integer type of width exactly 8 bits if
such a type exists and the standard includes do not define it. */
#undef uint8_t
/*-
* SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2020 NKI/AVL, Netherlands Cancer Institute
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#pragma once
#if defined(_MSC_VER)
// These are Microsoft Visual C++ special settings
// the iso646 file contains the C++ keywords that are
// otherwise not recognized.
#include <ciso646>
#define snprintf _snprintf
// Disable some warnings
#pragma warning (disable : 4996)
#pragma warning (disable : 4355)
#endif
/* define if the Boost library is available */
#undef HAVE_BOOST
/* define if the Boost::IOStreams library is available */
#undef HAVE_BOOST_IOSTREAMS
/* define if the Boost::Regex library is available */
#undef HAVE_BOOST_REGEX
/* define if the Boost::Thread library is available */
#undef HAVE_BOOST_THREAD
/* define if the compiler supports basic C++17 syntax */
#undef HAVE_CXX17
/* Define to 1 if you have the <dlfcn.h> header file. */
#undef HAVE_DLFCN_H
/* Define to 1 if you have the `floor' function. */
#undef HAVE_FLOOR
/* Define to 1 if you have the <inttypes.h> header file. */
#undef HAVE_INTTYPES_H
/* Define to 1 if LIBBZ2 is found */
#undef HAVE_LIBBZ2
/* Define to 1 if LIBZ is found */
#undef HAVE_LIBZ
/* Define to 1 if your system has a GNU libc compatible `malloc' function, and
to 0 otherwise. */
#undef HAVE_MALLOC
/* Define to 1 if you have the <memory.h> header file. */
#undef HAVE_MEMORY_H
/* Define to 1 if you have the `pow' function. */
#undef HAVE_POW
/* Define to 1 if the system has the type `ptrdiff_t'. */
#undef HAVE_PTRDIFF_T
/* Define to 1 if you have the `rint' function. */
#undef HAVE_RINT
/* Define to 1 if you have the `sqrt' function. */
#undef HAVE_SQRT
/* Define to 1 if you have the <stdint.h> header file. */
#undef HAVE_STDINT_H
/* Define to 1 if you have the <stdlib.h> header file. */
#undef HAVE_STDLIB_H
/* Define to 1 if you have the `strchr' function. */
#undef HAVE_STRCHR
/* Define to 1 if you have the `strerror' function. */
#undef HAVE_STRERROR
/* Define to 1 if you have the <strings.h> header file. */
#undef HAVE_STRINGS_H
/* Define to 1 if you have the <string.h> header file. */
#undef HAVE_STRING_H
/* Define to 1 if you have the <sys/ioctl.h> header file. */
#undef HAVE_SYS_IOCTL_H
/* Define to 1 if you have the <sys/stat.h> header file. */
#undef HAVE_SYS_STAT_H
/* Define to 1 if you have the <sys/types.h> header file. */
#undef HAVE_SYS_TYPES_H
/* Define to 1 if you have the <termios.h> header file. */
#undef HAVE_TERMIOS_H
/* Define to 1 if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H
/* Define to 1 if the system has the type `_Bool'. */
#undef HAVE__BOOL
/* Define to the sub-directory where libtool stores uninstalled libraries. */
#undef LT_OBJDIR
/* Define to 1 if you have the ANSI C header files. */
#undef STDC_HEADERS
/* Define for Solaris 2.5.1 so the uint32_t typedef from <sys/synch.h>,
<pthread.h>, or <semaphore.h> is not used. If the typedef were allowed, the
#define below would cause a syntax error. */
#undef _UINT32_T
/* Define for Solaris 2.5.1 so the uint64_t typedef from <sys/synch.h>,
<pthread.h>, or <semaphore.h> is not used. If the typedef were allowed, the
#define below would cause a syntax error. */
#undef _UINT64_T
/* Define for Solaris 2.5.1 so the uint8_t typedef from <sys/synch.h>,
<pthread.h>, or <semaphore.h> is not used. If the typedef were allowed, the
#define below would cause a syntax error. */
#undef _UINT8_T
/* Define to `__inline__' or `__inline' if that's what the C compiler
calls it, or to nothing if 'inline' is not supported under any name. */
#ifndef __cplusplus
#undef inline
#endif
/* Define to the type of a signed integer type of width exactly 32 bits if
such a type exists and the standard includes do not define it. */
#undef int32_t
/* Define to the type of a signed integer type of width exactly 64 bits if
such a type exists and the standard includes do not define it. */
#undef int64_t
/* Define to the type of a signed integer type of width exactly 8 bits if such
a type exists and the standard includes do not define it. */
#undef int8_t
/* Define to rpl_malloc if the replacement function should be used. */
#undef malloc
/* Define to `unsigned int' if <sys/types.h> does not define. */
#undef size_t
/* Define to the type of an unsigned integer type of width exactly 16 bits if
such a type exists and the standard includes do not define it. */
#undef uint16_t
/* Define to the type of an unsigned integer type of width exactly 32 bits if
such a type exists and the standard includes do not define it. */
#undef uint32_t
/* Define to the type of an unsigned integer type of width exactly 64 bits if
such a type exists and the standard includes do not define it. */
#undef uint64_t
/* Define to the type of an unsigned integer type of width exactly 8 bits if
such a type exists and the standard includes do not define it. */
#undef uint8_t
/*-
* SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2020 NKI/AVL, Netherlands Cancer Institute
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#pragma once
#include <unordered_map>
#include <clipper/clipper.h>
#include "cif++/Structure.hpp"
namespace mmcif
{
class DistanceMap
{
public:
DistanceMap(const Structure& p, const clipper::Spacegroup& spacegroup, const clipper::Cell& cell,
float maxDistance);
// simplified version for subsets of atoms (used in refining e.g.)
// DistanceMap(const Structure& p, const std::vector<Atom>& atoms);
DistanceMap(const DistanceMap&) = delete;
DistanceMap& operator=(const DistanceMap&) = delete;
float operator()(const Atom& a, const Atom& b) const;
std::vector<Atom> near(const Atom& a, float maxDistance = 3.5f) const;
std::vector<Atom> near(const Point& p, float maxDistance = 3.5f) const;
static clipper::Coord_orth
CalculateOffsetForCell(const Structure& p, const clipper::Spacegroup& spacegroup, const clipper::Cell& cell);
static std::vector<clipper::RTop_orth>
AlternativeSites(const clipper::Spacegroup& spacegroup, const clipper::Cell& cell);
private:
typedef std::map<std::tuple<size_t,size_t>,std::tuple<float,int32_t>> DistMap;
void AddDistancesForAtoms(const Residue& a, const Residue& b, DistMap& dm, int32_t rtix);
const Structure& structure;
size_t dim;
std::unordered_map<std::string,size_t> index;
std::map<size_t,std::string> rIndex;
float mMaxDistance, mMaxDistanceSQ;
std::vector<std::tuple<float,int32_t>> mA;
std::vector<size_t> mIA, mJA;
Point mD; // needed to move atoms to center
std::vector<clipper::RTop_orth> mRtOrth;
};
}
/*-
* SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2020 NKI/AVL, Netherlands Cancer Institute
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#pragma once
#include <clipper/clipper.h>
#include "cif++/Structure.hpp"
namespace mmcif
{
template<typename FTYPE>
class Map
{
public:
typedef FTYPE ftype;
typedef typename clipper::Xmap<ftype> Xmap;
Map();
~Map();
void calculateStats();
double rmsDensity() const { return mRMSDensity; }
double meanDensity() const { return mMeanDensity; }
operator Xmap& () { return mMap; }
operator const Xmap& () const { return mMap; }
Xmap& get() { return mMap; }
const Xmap& get() const { return mMap; }
// These routines work with CCP4 map files
void read(const std::string& f);
void write(const std::string& f);
void write_masked(std::ostream& os, clipper::Grid_range range);
void write_masked(const std::string& f,
clipper::Grid_range range);
clipper::Spacegroup spacegroup() const { return mMap.spacegroup(); }
clipper::Cell cell() const { return mMap.cell(); }
private:
Xmap mMap;
double mMinDensity, mMaxDensity;
double mRMSDensity, mMeanDensity;
};
using clipper::HKL_info;
using clipper::HKL_data;
using clipper::data32::F_phi;
using clipper::data32::F_sigF;
using clipper::data32::Phi_fom;
using clipper::data32::Flag;
using clipper::Spacegroup;
using clipper::Cell;
using clipper::Grid_sampling;
// --------------------------------------------------------------------
bool IsMTZFile(const std::string& p);
// --------------------------------------------------------------------
template<typename FTYPE>
class MapMaker
{
public:
typedef Map<FTYPE> MapType;
typedef typename MapType::Xmap Xmap;
enum AnisoScalingFlag {
as_None, as_Observed, as_Calculated
};
MapMaker();
~MapMaker();
MapMaker(const MapMaker&) = delete;
MapMaker& operator=(const MapMaker&) = delete;
void loadMTZ(const std::string& mtzFile,
float samplingRate,
std::initializer_list<std::string> fbLabels = { "FWT", "PHWT" },
std::initializer_list<std::string> fdLabels = { "DELFWT", "PHDELWT" },
std::initializer_list<std::string> foLabels = { "FP", "SIGFP" },
std::initializer_list<std::string> fcLabels = { "FC_ALL", "PHIC_ALL" },
std::initializer_list<std::string> faLabels = { "FAN", "PHAN" });
void loadMaps(
const std::string& fbMapFile,
const std::string& fdMapFile,
float reshi, float reslo);
// following works on both mtz files and structure factor files in CIF format
void calculate(const std::string& hklin,
const Structure& structure,
bool noBulk, AnisoScalingFlag anisoScaling,
float samplingRate, bool electronScattering = false,
std::initializer_list<std::string> foLabels = { "FP", "SIGFP" },
std::initializer_list<std::string> freeLabels = { "FREE" });
void recalc(const Structure& structure,
bool noBulk, AnisoScalingFlag anisoScaling,
float samplingRate, bool electronScattering = false);
void printStats();
void writeMTZ(const std::string& file,
const std::string& project, const std::string& crystal);
MapType& fb() { return mFb; }
MapType& fd() { return mFd; }
MapType& fa() { return mFa; }
const MapType& fb() const { return mFb; }
const MapType& fd() const { return mFd; }
const MapType& fa() const { return mFa; }
double resLow() const { return mResLow; }
double resHigh() const { return mResHigh; }
const Spacegroup& spacegroup() const { return mHKLInfo.spacegroup(); }
const Cell& cell() const { return mHKLInfo.cell(); }
const Grid_sampling& gridSampling() const { return mGrid; }
private:
void loadFoFreeFromReflectionsFile(const std::string& hklin);
void loadFoFreeFromMTZFile(const std::string& hklin,
std::initializer_list<std::string> foLabels,
std::initializer_list<std::string> freeLabels);
void fixMTZ();
MapType mFb, mFd, mFa;
Grid_sampling mGrid;
float mSamplingRate;
double mResLow, mResHigh;
int mNumRefln = 1000, mNumParam = 20;
// Cached raw data
HKL_info mHKLInfo;
HKL_data<F_sigF> mFoData;
HKL_data<Flag> mFreeData;
HKL_data<F_phi> mFcData, mFbData, mFdData, mFaData;
HKL_data<Phi_fom> mPhiFomData;
};
}
...@@ -32,8 +32,6 @@ ...@@ -32,8 +32,6 @@
#include <boost/math/quaternion.hpp> #include <boost/math/quaternion.hpp>
#include "clipper/core/coords.h"
namespace mmcif namespace mmcif
{ {
...@@ -60,7 +58,7 @@ struct PointF ...@@ -60,7 +58,7 @@ struct PointF
PointF() : mX(0), mY(0), mZ(0) {} PointF() : mX(0), mY(0), mZ(0) {}
PointF(FType x, FType y, FType z) : mX(x), mY(y), mZ(z) {} PointF(FType x, FType y, FType z) : mX(x), mY(y), mZ(z) {}
PointF(const clipper::Coord_orth& pt): mX(pt[0]), mY(pt[1]), mZ(pt[2]) {} // PointF(const clipper::Coord_orth& pt): mX(pt[0]), mY(pt[1]), mZ(pt[2]) {}
template<typename PF> template<typename PF>
PointF(const PointF<PF>& pt) PointF(const PointF<PF>& pt)
...@@ -68,13 +66,13 @@ struct PointF ...@@ -68,13 +66,13 @@ struct PointF
, mY(static_cast<F>(pt.mY)) , mY(static_cast<F>(pt.mY))
, mZ(static_cast<F>(pt.mZ)) {} , mZ(static_cast<F>(pt.mZ)) {}
PointF& operator=(const clipper::Coord_orth& rhs) // PointF& operator=(const clipper::Coord_orth& rhs)
{ // {
mX = rhs[0]; // mX = rhs[0];
mY = rhs[1]; // mY = rhs[1];
mZ = rhs[2]; // mZ = rhs[2];
return *this; // return *this;
} // }
template<typename PF> template<typename PF>
PointF& operator=(const PointF<PF>& rhs) PointF& operator=(const PointF<PF>& rhs)
...@@ -171,10 +169,10 @@ struct PointF ...@@ -171,10 +169,10 @@ struct PointF
mZ = p.R_component_4(); mZ = p.R_component_4();
} }
operator clipper::Coord_orth() const // operator clipper::Coord_orth() const
{ // {
return clipper::Coord_orth(mX, mY, mZ); // return clipper::Coord_orth(mX, mY, mZ);
} // }
operator std::tuple<const FType&, const FType&, const FType&>() const operator std::tuple<const FType&, const FType&, const FType&>() const
{ {
......
/*-
* SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2020 NKI/AVL, Netherlands Cancer Institute
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#pragma once
#include "cif++/ResolutionCalculator.hpp"
#include <clipper/clipper.h>
#include <cmath>
namespace mmcif
{
// --------------------------------------------------------------------
class ResolutionCalculator
{
public:
ResolutionCalculator(double a, double b, double c,
double alpha, double beta, double gamma);
ResolutionCalculator(const clipper::Cell& cell);
double operator()(int h, int k, int l) const
{
double tmpres = h * h * mCoefs[0] + h * k * mCoefs[1] +
h * l * mCoefs[2] + k * k * mCoefs[3] +
k * l * mCoefs[4] + l * l * mCoefs[5];
return 1.0 / std::sqrt(tmpres);
}
private:
double mCoefs[6];
};
}
/*-
* SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2020 NKI/AVL, Netherlands Cancer Institute
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#pragma once
#include "cif++/MapMaker.hpp"
#include "cif++/DistanceMap.hpp"
#include "cif++/BondMap.hpp"
namespace mmcif
{
// --------------------------------------------------------------------
struct AtomData;
class BoundingBox;
struct ResidueStatistics
{
std::string asymID;
int seqID;
std::string compID;
std::string authSeqID;
double RSR, SRSR, RSCCS, EDIAm, OPIA;
int ngrid;
};
std::ostream& operator<<(std::ostream& os, const ResidueStatistics& st);
// --------------------------------------------------------------------
class StatsCollector
{
public:
StatsCollector(const StatsCollector&) = delete;
StatsCollector& operator=(const StatsCollector&) = delete;
StatsCollector(const mmcif::MapMaker<float>& mm,
mmcif::Structure& structure, bool electronScattering);
virtual std::vector<ResidueStatistics> collect() const;
virtual std::vector<ResidueStatistics> collect(const std::string& asymID,
int resFirst, int resLast, bool authNameSpace = true) const;
virtual ResidueStatistics collect(std::initializer_list<const mmcif::Residue*> residues) const;
virtual ResidueStatistics collect(std::initializer_list<mmcif::Atom> atoms) const;
virtual ResidueStatistics collect(const std::vector<mmcif::Atom>& atoms) const;
protected:
// asym-seqid-compid
std::vector<ResidueStatistics> collect(
const std::vector<std::tuple<std::string,int,std::string,std::string>>& residues,
BoundingBox& bbox, bool addWaters) const;
void initialize();
virtual void calculate(std::vector<AtomData>& atomData) const;
struct cmpGPt
{
bool operator()(const clipper::Coord_grid& a, const clipper::Coord_grid& b) const
{
int d = a.u() - b.u();
if (d == 0)
d = a.v() - b.v();
if (d == 0)
d = a.w() - b.w();
return d < 0;
}
};
typedef std::map<clipper::Coord_grid,double,cmpGPt> GridPtDataMap;
mmcif::Structure& mStructure;
const mmcif::MapMaker<float>& mMapMaker;
clipper::Spacegroup mSpacegroup;
clipper::Cell mCell;
clipper::Grid_sampling mGrid;
float mResHigh, mResLow;
bool mElectronScattering;
std::map<std::string,std::pair<double,double>> mRmsScaled;
void collectSums(std::vector<AtomData>& atomData, GridPtDataMap& gridPointDensity) const;
void sumDensity(std::vector<AtomData>& atomData,
GridPtDataMap& gridPointDensity, std::map<std::string,std::vector<double>>& zScoresPerAsym) const;
// Other variables we cache
double mMeanDensityFb, mRMSDensityFb, mRMSDensityFd;
double mSZ; // average electron density in cell
double mVF; // degrees of freedom
double mVC; // cell volume?
};
// --------------------------------------------------------------------
class EDIAStatsCollector : public StatsCollector
{
public:
EDIAStatsCollector(mmcif::MapMaker<float>& mm,
mmcif::Structure& structure, bool electronScattering,
const mmcif::BondMap& bondMap);
protected:
virtual void calculate(std::vector<AtomData>& atomData) const;
mmcif::DistanceMap mDistanceMap;
const mmcif::BondMap& mBondMap;
std::map<mmcif::AtomType,float> mRadii;
};
}
...@@ -28,12 +28,6 @@ ...@@ -28,12 +28,6 @@
#include <numeric> #include <numeric>
#include <boost/math/quaternion.hpp>
#include <boost/any.hpp>
#include <clipper/core/coords.h>
#include "cif++/AtomType.hpp" #include "cif++/AtomType.hpp"
#include "cif++/Point.hpp" #include "cif++/Point.hpp"
#include "cif++/Compound.hpp" #include "cif++/Compound.hpp"
...@@ -87,10 +81,10 @@ class Atom ...@@ -87,10 +81,10 @@ class Atom
Point location() const; Point location() const;
void location(Point p); void location(Point p);
Atom symmetryCopy(const Point& d, const clipper::RTop_orth& rt); // Atom symmetryCopy(const Point& d, const clipper::RTop_orth& rt);
bool isSymmetryCopy() const; // bool isSymmetryCopy() const;
std::string symmetry() const; // std::string symmetry() const;
const clipper::RTop_orth& symop() const; // const clipper::RTop_orth& symop() const;
const Compound& comp() const; const Compound& comp() const;
bool isWater() const; bool isWater() const;
...@@ -126,8 +120,8 @@ class Atom ...@@ -126,8 +120,8 @@ class Atom
bool operator==(const Atom& rhs) const; bool operator==(const Atom& rhs) const;
// get clipper format Atom // // get clipper format Atom
clipper::Atom toClipper() const; // clipper::Atom toClipper() const;
// Radius calculation based on integrating the density until perc of electrons is found // Radius calculation based on integrating the density until perc of electrons is found
void calculateRadius(float resHigh, float resLow, float perc); void calculateRadius(float resHigh, float resLow, float perc);
......
...@@ -26,137 +26,9 @@ ...@@ -26,137 +26,9 @@
#pragma once #pragma once
#include "cif++/Structure.hpp"
namespace mmcif namespace mmcif
{ {
// --------------------------------------------------------------------
// Functions to use when working with symmetry stuff
clipper::Coord_orth CalculateOffsetForCell(const Structure& p, const clipper::Spacegroup& spacegroup, const clipper::Cell& cell);
std::vector<clipper::RTop_orth> AlternativeSites(const clipper::Spacegroup& spacegroup, const clipper::Cell& cell);
int GetSpacegroupNumber(std::string spacegroup); // alternative for clipper's parsing code int GetSpacegroupNumber(std::string spacegroup); // alternative for clipper's parsing code
// std::string SpacegroupToHall(std::string spacegroup);
// --------------------------------------------------------------------
// To iterate over all symmetry copies of an atom
class SymmetryAtomIteratorFactory
{
public:
// SymmetryAtomIteratorFactory(const Structure& p);
// SymmetryAtomIteratorFactory(const Structure& p, const clipper::Spacegroup& spacegroup, const clipper::Cell& cell)
// : mSpacegroupNr(spacegroup.spacegroup_number())
// , mSpacegroup(spacegroup)
// , mD(CalculateOffsetForCell(p, spacegroup, cell))
// , mRtOrth(AlternativeSites(spacegroup, cell))
// , mCell(cell) {}
SymmetryAtomIteratorFactory(const Structure& p, int spacegroupNr, const clipper::Cell& cell);
SymmetryAtomIteratorFactory(const SymmetryAtomIteratorFactory&) = delete;
SymmetryAtomIteratorFactory& operator=(const SymmetryAtomIteratorFactory&) = delete;
class SymmetryAtomIterator : public std::iterator<std::forward_iterator_tag, const Atom>
{
public:
typedef std::iterator<std::forward_iterator_tag, const Atom> baseType;
typedef typename baseType::pointer pointer;
typedef typename baseType::reference reference;
SymmetryAtomIterator(const SymmetryAtomIteratorFactory& factory, const Atom& atom)
: m_f(&factory), m_i(0), m_a(atom), m_c(atom) {}
SymmetryAtomIterator(const SymmetryAtomIteratorFactory& factory, const Atom& atom, int)
: SymmetryAtomIterator(factory, atom)
{
m_i = m_f->mRtOrth.size();
}
SymmetryAtomIterator(const SymmetryAtomIterator& iter)
: m_f(iter.m_f), m_i(iter.m_i), m_a(iter.m_a), m_c(iter.m_c) {}
SymmetryAtomIterator& operator=(const SymmetryAtomIterator& iter)
{
if (this != &iter)
{
m_f = iter.m_f;
m_i = iter.m_i;
m_a = iter.m_a;
m_c = iter.m_c;
}
return *this;
}
reference operator*() { return m_c; }
pointer operator->() { return &m_c; }
SymmetryAtomIterator operator++()
{
if (++m_i < m_f->mRtOrth.size())
m_c = m_a.symmetryCopy(m_f->mD, m_f->mRtOrth[m_i]);
return *this;
}
SymmetryAtomIterator operator++(int)
{
SymmetryAtomIterator result(*this);
this->operator++();
return result;
}
bool operator==(const SymmetryAtomIterator& iter) const
{
return m_f == iter.m_f and m_i == iter.m_i;
}
bool operator!=(const SymmetryAtomIterator& iter) const
{
return m_f != iter.m_f or m_i != iter.m_i;
}
private:
const SymmetryAtomIteratorFactory* m_f;
size_t m_i;
Atom m_a, m_c;
};
class SymmetryAtomIteratorRange
{
public:
SymmetryAtomIteratorRange(const SymmetryAtomIteratorFactory& f, const Atom& a)
: m_f(f), m_a(a) {}
SymmetryAtomIterator begin()
{
return SymmetryAtomIterator(m_f, m_a);
}
SymmetryAtomIterator end()
{
return SymmetryAtomIterator(m_f, m_a, 1);
}
private:
const SymmetryAtomIteratorFactory& m_f;
Atom m_a;
};
SymmetryAtomIteratorRange operator()(const Atom& a) const
{
return SymmetryAtomIteratorRange(*this, a);
}
std::string symop_mmcif(const Atom& a) const;
private:
int mSpacegroupNr;
clipper::Spacegroup mSpacegroup;
Point mD; // needed to move atoms to center
std::vector<clipper::RTop_orth> mRtOrth;
clipper::Cell mCell;
};
} }
...@@ -24,6 +24,8 @@ ...@@ -24,6 +24,8 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#pragma once
#include <vector> #include <vector>
#include <string> #include <string>
#include <tuple> #include <tuple>
......
...@@ -24,6 +24,8 @@ ...@@ -24,6 +24,8 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#include <cmath>
#include "cif++/AtomType.hpp" #include "cif++/AtomType.hpp"
#include "cif++/Cif++.hpp" #include "cif++/Cif++.hpp"
...@@ -35,7 +37,7 @@ namespace mmcif ...@@ -35,7 +37,7 @@ namespace mmcif
namespace data namespace data
{ {
const float kNA = nan("1"); const float kNA = std::nan("1");
const AtomTypeInfo kKnownAtoms[] = const AtomTypeInfo kKnownAtoms[] =
{ {
......
/*-
* SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2020 NKI/AVL, Netherlands Cancer Institute
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "cif++/Config.hpp"
#include "cif++/Cif++.hpp"
#include "cif++/BondMap.hpp"
#include "cif++/Compound.hpp"
#include "cif++/CifUtils.hpp"
using namespace std;
namespace mmcif
{
// --------------------------------------------------------------------
BondMap::BondMap(const Structure& p)
{
auto atoms = p.atoms();
dim = atoms.size();
// bond = vector<bool>(dim * (dim - 1), false);
for (auto& atom: atoms)
{
size_t ix = index.size();
index[atom.id()] = ix;
};
auto bindAtoms = [this](const string& a, const string& b)
{
uint32_t ixa = index[a];
uint32_t ixb = index[b];
bond.insert(key(ixa, ixb));
};
auto linkAtoms = [this,&bindAtoms](const string& a, const string& b)
{
bindAtoms(a, b);
link[a].insert(b);
link[b].insert(a);
};
cif::Datablock& db = p.getFile().data();
// collect all compounds first
set<string> compounds;
for (auto c: db["chem_comp"])
compounds.insert(c["id"].as<string>());
// make sure we also have all residues in the polyseq
for (auto m: db["entity_poly_seq"])
{
string c = m["mon_id"].as<string>();
if (compounds.count(c))
continue;
if (cif::VERBOSE > 1)
cerr << "Warning: mon_id " << c << " is missing in the chem_comp category" << endl;
compounds.insert(c);
}
cif::Progress progress(compounds.size(), "Creating bond map");
// some helper indices to speed things up a bit
map<tuple<string,int,string>,string> atomMapByAsymSeqAndAtom;
for (auto& a: p.atoms())
{
auto key = make_tuple(a.labelAsymID(), a.labelSeqID(), a.labelAtomID());
atomMapByAsymSeqAndAtom[key] = a.id();
}
// first link all residues in a polyseq
string lastAsymID;
int lastSeqID = 0;
for (auto r: db["pdbx_poly_seq_scheme"])
{
string asymID;
int seqID;
cif::tie(asymID, seqID) = r.get("asym_id", "seq_id");
if (asymID != lastAsymID) // first in a new sequece
{
lastAsymID = asymID;
lastSeqID = seqID;
continue;
}
auto c = atomMapByAsymSeqAndAtom[make_tuple(asymID, lastSeqID, "C")];
auto n = atomMapByAsymSeqAndAtom[make_tuple(asymID, seqID, "N")];
// auto c = db["atom_site"].find(cif::Key("label_asym_id") == asymID and cif::Key("label_seq_id") == lastSeqID and cif::Key("label_atom_id") == "C");
// if (c.size() != 1 and VERBOSE > 1)
// cerr << "Unexpected number (" << c.size() << ") of atoms with atom ID C in asym_id " << asymID << " with seq id " << lastSeqID << endl;
//
// auto n = db["atom_site"].find(cif::Key("label_asym_id") == asymID and cif::Key("label_seq_id") == seqID and cif::Key("label_atom_id") == "N");
// if (n.size() != 1 and VERBOSE > 1)
// cerr << "Unexpected number (" << n.size() << ") of atoms with atom ID N in asym_id " << asymID << " with seq id " << seqID << endl;
//
// if (not (c.empty() or n.empty()))
// bindAtoms(c.front()["id"].as<string>(), n.front()["id"].as<string>());
if (not (c.empty() or n.empty()))
bindAtoms(c, n);
lastSeqID = seqID;
}
for (auto l: db["struct_conn"])
{
string asym1, asym2, atomId1, atomId2;
int seqId1 = 0, seqId2 = 0;
cif::tie(asym1, asym2, atomId1, atomId2, seqId1, seqId2) =
l.get("ptnr1_label_asym_id", "ptnr2_label_asym_id",
"ptnr1_label_atom_id", "ptnr2_label_atom_id",
"ptnr1_label_seq_id", "ptnr2_label_seq_id");
string a = atomMapByAsymSeqAndAtom[make_tuple(asym1, seqId1, atomId1)];
string b = atomMapByAsymSeqAndAtom[make_tuple(asym2, seqId2, atomId2)];
// auto a =
// l["ptnr1_label_seq_id"].empty() ?
// db["atom_site"].find(cif::Key("label_asym_id") == asym1 and cif::Key("label_atom_id") == atomId1) :
// db["atom_site"].find(cif::Key("label_asym_id") == asym1 and cif::Key("label_seq_id") == seqId1 and cif::Key("label_atom_id") == atomId1);
//
// if (a.size() != 1 and VERBOSE > 1)
// cerr << "Unexpected number (" << a.size() << ") of atoms for link with asym_id " << asym1 << " seq_id " << seqId1 << " atom_id " << atomId1 << endl;
// auto b =
// l["ptnr2_label_seq_id"].empty() ?
// db["atom_site"].find(cif::Key("label_asym_id") == asym2 and cif::Key("label_atom_id") == atomId2) :
// db["atom_site"].find(cif::Key("label_asym_id") == asym2 and cif::Key("label_seq_id") == seqId2 and cif::Key("label_atom_id") == atomId2);
//
// if (b.size() != 1 and VERBOSE > 1)
// cerr << "Unexpected number (" << b.size() << ") of atoms for link with asym_id " << asym2 << " seq_id " << seqId2 << " atom_id " << atomId2 << endl;
// if (not (a.empty() or b.empty()))
// linkAtoms(a.front()["id"].as<string>(), b.front()["id"].as<string>());
if (not (a.empty() or b.empty()))
linkAtoms(a, b);
}
// then link all atoms in the compounds
for (auto c: compounds)
{
auto* compound = mmcif::Compound::create(c);
if (not compound)
{
if (cif::VERBOSE)
cerr << "Missing compound information for " << c << endl;
continue;
}
if (compound->isWater())
{
if (cif::VERBOSE)
cerr << "skipping water in bond map calculation" << endl;
continue;
}
// loop over poly_seq_scheme
for (auto r: db["pdbx_poly_seq_scheme"].find(cif::Key("mon_id") == c))
{
string asymID;
int seqID;
cif::tie(asymID, seqID) = r.get("asym_id", "seq_id");
vector<Atom> rAtoms;
copy_if(atoms.begin(), atoms.end(), back_inserter(rAtoms),
[&](auto& a) { return a.labelAsymID() == asymID and a.labelSeqID() == seqID; });
for (uint32_t i = 0; i + 1 < rAtoms.size(); ++i)
{
for (uint32_t j = i + 1; j < rAtoms.size(); ++j)
{
if (compound->atomsBonded(rAtoms[i].labelAtomID(), rAtoms[j].labelAtomID()))
bindAtoms(rAtoms[i].id(), rAtoms[j].id());
}
}
}
// loop over pdbx_nonpoly_scheme
for (auto r: db["pdbx_nonpoly_scheme"].find(cif::Key("mon_id") == c))
{
string asymID;
cif::tie(asymID) = r.get("asym_id");
vector<Atom> rAtoms;
copy_if(atoms.begin(), atoms.end(), back_inserter(rAtoms),
[&](auto& a) { return a.labelAsymID() == asymID; });
// for (auto a: db["atom_site"].find(cif::Key("label_asym_id") == asymID))
// rAtoms.push_back(p.getAtomByID(a["id"].as<string>()));
for (uint32_t i = 0; i + 1 < rAtoms.size(); ++i)
{
for (uint32_t j = i + 1; j < rAtoms.size(); ++j)
{
if (compound->atomsBonded(rAtoms[i].labelAtomID(), rAtoms[j].labelAtomID()))
{
uint32_t ixa = index[rAtoms[i].id()];
uint32_t ixb = index[rAtoms[j].id()];
bond.insert(key(ixa, ixb));
}
}
}
}
}
// start by creating an index for single bonds
//cout << "Maken van b1_2 voor " << bond.size() << " bindingen" << endl;
multimap<uint32_t,uint32_t> b1_2;
for (auto& bk: bond)
{
uint32_t a, b;
tie(a, b) = dekey(bk);
b1_2.insert({ a, b });
b1_2.insert({ b, a });
}
//cout << "Afmeting b1_2: " << b1_2.size() << endl;
multimap<uint32_t,uint32_t> b1_3;
for (uint32_t i = 0; i < dim; ++i)
{
auto a = b1_2.equal_range(i);
vector<uint32_t> s;
for (auto j = a.first; j != a.second; ++j)
s.push_back(j->second);
for (size_t si1 = 0; si1 + 1 < s.size(); ++si1)
{
for (size_t si2 = si1 + 1; si2 < s.size(); ++si2)
{
uint32_t x = s[si1];
uint32_t y = s[si2];
if (isBonded(x, y))
continue;
b1_3.insert({ x, y });
b1_3.insert({ y, x });
}
}
}
//cout << "Afmeting b1_3: " << b1_3.size() << endl;
for (uint32_t i = 0; i < dim; ++i)
{
auto a1 = b1_2.equal_range(i);
auto a2 = b1_3.equal_range(i);
for (auto ai1 = a1.first; ai1 != a1.second; ++ai1)
{
for (auto ai2 = a2.first; ai2 != a2.second; ++ai2)
{
uint32_t b1 = ai1->second;
uint32_t b2 = ai2->second;
if (isBonded(b1, b2))
continue;
bond_1_4.insert(key(b1, b2));
}
}
}
//cout << "Afmeting b1_4: " << bond_1_4.size() << endl;
}
vector<string> BondMap::linked(const Atom& a) const
{
auto i = link.find(a.id());
vector<string> result;
if (i != link.end())
result = vector<string>(i->second.begin(), i->second.end());
return result;
}
}
...@@ -34,13 +34,7 @@ ...@@ -34,13 +34,7 @@
#include <numeric> #include <numeric>
#include <fstream> #include <fstream>
#if __has_include(<filesystem>)
#include <filesystem> #include <filesystem>
namespace fs = std::filesystem;
#elif __has_include(<boost/filesystem.hpp>)
#include <boost/filesystem.hpp>
namespace fs = boost::filesystem;
#endif
#include <boost/algorithm/string.hpp> #include <boost/algorithm/string.hpp>
#include <boost/iostreams/filtering_stream.hpp> #include <boost/iostreams/filtering_stream.hpp>
...@@ -56,6 +50,7 @@ namespace fs = boost::filesystem; ...@@ -56,6 +50,7 @@ namespace fs = boost::filesystem;
using namespace std; using namespace std;
namespace ba = boost::algorithm; namespace ba = boost::algorithm;
namespace io = boost::iostreams; namespace io = boost::iostreams;
namespace fs = std::filesystem;
namespace cif namespace cif
{ {
......
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -35,13 +35,12 @@ ...@@ -35,13 +35,12 @@
#include <boost/format.hpp> #include <boost/format.hpp>
#include <boost/numeric/ublas/matrix.hpp> #include <boost/numeric/ublas/matrix.hpp>
#include <clipper/core/spacegroup.h>
#include "cif++/PDB2Cif.hpp" #include "cif++/PDB2Cif.hpp"
#include "cif++/AtomType.hpp" #include "cif++/AtomType.hpp"
#include "cif++/Compound.hpp" #include "cif++/Compound.hpp"
#include "cif++/PDB2CifRemark3.hpp" #include "cif++/PDB2CifRemark3.hpp"
#include "cif++/CifUtils.hpp" #include "cif++/CifUtils.hpp"
#include "cif++/Symmetry.hpp"
using namespace std; using namespace std;
namespace ba = boost::algorithm; namespace ba = boost::algorithm;
...@@ -4928,8 +4927,7 @@ void PDBFileParser::ParseCrystallographic() ...@@ -4928,8 +4927,7 @@ void PDBFileParser::ParseCrystallographic()
try try
{ {
spaceGroup = vS(56, 66); spaceGroup = vS(56, 66);
clipper::Spacegroup sg(clipper::Spgr_descr{spaceGroup}); intTablesNr = std::to_string(mmcif::GetSpacegroupNumber(spaceGroup));
intTablesNr = to_string(sg.spacegroup_number());
} }
catch (...) catch (...)
{ {
......
/*-
* SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2020 NKI/AVL, Netherlands Cancer Institute
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "cif++/ResolutionCalculator.hpp"
#include "cif++/Point.hpp"
using namespace std;
namespace mmcif
{
ResolutionCalculator::ResolutionCalculator(const clipper::Cell& cell)
: ResolutionCalculator(cell.a(), cell.b(), cell.c(),
180 * cell.alpha() / kPI,
180 * cell.beta() / kPI,
180 * cell.gamma() / kPI)
{
}
ResolutionCalculator::ResolutionCalculator(double a, double b, double c,
double alpha, double beta, double gamma)
{
double deg2rad = atan(1.0) / 45.0;
double ca = cos(deg2rad * alpha);
double sa = sin(deg2rad * alpha);
double cb = cos(deg2rad * beta);
double sb = sin(deg2rad * beta);
double cg = cos(deg2rad * gamma);
double sg = sin(deg2rad * gamma);
double cast = (cb * cg - ca) / (sb * sg);
double cbst = (cg * ca - cb) / (sg * sa);
double cgst = (ca * cb - cg) / (sa * sb);
double sast = sqrt(1 - cast * cast);
double sbst = sqrt(1 - cbst * cbst);
double sgst = sqrt(1 - cgst * cgst);
double ast = 1 / (a * sb * sgst);
double bst = 1 / (b * sg * sast);
double cst = 1 / (c * sa * sbst);
mCoefs[0] = ast * ast;
mCoefs[1] = 2 * ast * bst * cgst;
mCoefs[2] = 2 * ast * cst * cbst;
mCoefs[3] = bst * bst;
mCoefs[4] = 2 * bst * cst * cast;
mCoefs[5] = cst * cst;
}
}
...@@ -47,7 +47,7 @@ namespace fs = boost::filesystem; ...@@ -47,7 +47,7 @@ namespace fs = boost::filesystem;
#include "cif++/PDB2Cif.hpp" #include "cif++/PDB2Cif.hpp"
#include "cif++/CifParser.hpp" #include "cif++/CifParser.hpp"
#include "cif++/Cif2PDB.hpp" #include "cif++/Cif2PDB.hpp"
#include "cif++/AtomShape.hpp" // #include "cif++/AtomShape.hpp"
using namespace std; using namespace std;
...@@ -190,7 +190,7 @@ struct AtomImpl ...@@ -190,7 +190,7 @@ struct AtomImpl
, mRefcount(1), mRow(i.mRow), mCompound(i.mCompound) , mRefcount(1), mRow(i.mRow), mCompound(i.mCompound)
, mRadius(i.mRadius), mCachedProperties(i.mCachedProperties) , mRadius(i.mRadius), mCachedProperties(i.mCachedProperties)
, mSymmetryCopy(i.mSymmetryCopy), mClone(true) , mSymmetryCopy(i.mSymmetryCopy), mClone(true)
, mRTop(i.mRTop), mD(i.mD) // , mRTop(i.mRTop), mD(i.mD)
{ {
} }
...@@ -211,18 +211,18 @@ struct AtomImpl ...@@ -211,18 +211,18 @@ struct AtomImpl
prefetch(); prefetch();
} }
AtomImpl(const AtomImpl& impl, const Point& d, const clipper::RTop_orth& rt) // AtomImpl(const AtomImpl& impl, const Point& d, const clipper::RTop_orth& rt)
: mFile(impl.mFile), mID(impl.mID), mType(impl.mType), mAtomID(impl.mAtomID) // : mFile(impl.mFile), mID(impl.mID), mType(impl.mType), mAtomID(impl.mAtomID)
, mCompID(impl.mCompID), mAsymID(impl.mAsymID), mSeqID(impl.mSeqID) // , mCompID(impl.mCompID), mAsymID(impl.mAsymID), mSeqID(impl.mSeqID)
, mAltID(impl.mAltID), mLocation(impl.mLocation), mRefcount(1) // , mAltID(impl.mAltID), mLocation(impl.mLocation), mRefcount(1)
, mRow(impl.mRow), mCompound(impl.mCompound), mRadius(impl.mRadius) // , mRow(impl.mRow), mCompound(impl.mCompound), mRadius(impl.mRadius)
, mCachedProperties(impl.mCachedProperties) // , mCachedProperties(impl.mCachedProperties)
, mSymmetryCopy(true), mRTop(rt), mD(d) // , mSymmetryCopy(true), mRTop(rt), mD(d)
{ // {
mLocation += d; // mLocation += d;
mLocation = ((clipper::Coord_orth)mLocation).transform(rt); // mLocation = ((clipper::Coord_orth)mLocation).transform(rt);
mLocation -= d; // mLocation -= d;
} // }
void prefetch() void prefetch()
{ {
...@@ -245,52 +245,52 @@ struct AtomImpl ...@@ -245,52 +245,52 @@ struct AtomImpl
mCompound = Compound::create(compID); mCompound = Compound::create(compID);
} }
clipper::Atom toClipper() const // clipper::Atom toClipper() const
{ // {
clipper::Atom result; // clipper::Atom result;
result.set_coord_orth(mLocation); // result.set_coord_orth(mLocation);
if (mRow["occupancy"].empty()) // if (mRow["occupancy"].empty())
result.set_occupancy(1.0); // result.set_occupancy(1.0);
else // else
result.set_occupancy(mRow["occupancy"].as<float>()); // result.set_occupancy(mRow["occupancy"].as<float>());
string element = mRow["type_symbol"].as<string>(); // string element = mRow["type_symbol"].as<string>();
if (not mRow["pdbx_formal_charge"].empty()) // if (not mRow["pdbx_formal_charge"].empty())
{ // {
int charge = mRow["pdbx_formal_charge"].as<int>(); // int charge = mRow["pdbx_formal_charge"].as<int>();
if (abs(charge) > 1) // if (abs(charge) > 1)
element += to_string(charge); // element += to_string(charge);
if (charge < 0) // if (charge < 0)
element += '-'; // element += '-';
else // else
element += '+'; // element += '+';
} // }
result.set_element(element); // result.set_element(element);
if (not mRow["U_iso_or_equiv"].empty()) // if (not mRow["U_iso_or_equiv"].empty())
result.set_u_iso(mRow["U_iso_or_equiv"].as<float>()); // result.set_u_iso(mRow["U_iso_or_equiv"].as<float>());
else if (not mRow["B_iso_or_equiv"].empty()) // else if (not mRow["B_iso_or_equiv"].empty())
result.set_u_iso(mRow["B_iso_or_equiv"].as<float>() / (8 * kPI * kPI)); // result.set_u_iso(mRow["B_iso_or_equiv"].as<float>() / (8 * kPI * kPI));
else // else
throw runtime_error("Missing B_iso or U_iso"); // throw runtime_error("Missing B_iso or U_iso");
auto& db = *mFile.impl().mDb; // auto& db = *mFile.impl().mDb;
auto& cat = db["atom_site_anisotrop"]; // auto& cat = db["atom_site_anisotrop"];
auto r = cat[cif::Key("id") == mID]; // auto r = cat[cif::Key("id") == mID];
if (r.empty()) // if (r.empty())
result.set_u_aniso_orth(clipper::U_aniso_orth(nan("0"), 0, 0, 0, 0, 0)); // result.set_u_aniso_orth(clipper::U_aniso_orth(nan("0"), 0, 0, 0, 0, 0));
else // else
{ // {
float u11, u12, u13, u22, u23, u33; // float u11, u12, u13, u22, u23, u33;
cif::tie(u11, u12, u13, u22, u23, u33) = // cif::tie(u11, u12, u13, u22, u23, u33) =
r.get("U[1][1]", "U[1][2]", "U[1][3]", "U[2][2]", "U[2][3]", "U[3][3]"); // r.get("U[1][1]", "U[1][2]", "U[1][3]", "U[2][2]", "U[2][3]", "U[3][3]");
result.set_u_aniso_orth(clipper::U_aniso_orth(u11, u22, u33, u12, u13, u23)); // result.set_u_aniso_orth(clipper::U_aniso_orth(u11, u22, u33, u12, u13, u23));
} // }
return result; // return result;
} // }
void reference() void reference()
{ {
...@@ -423,9 +423,9 @@ struct AtomImpl ...@@ -423,9 +423,9 @@ struct AtomImpl
bool mSymmetryCopy = false; bool mSymmetryCopy = false;
bool mClone = false; bool mClone = false;
clipper::RTop_orth mRTop; // clipper::RTop_orth mRTop;
Point mD; // Point mD;
int32_t mRTix; // int32_t mRTix;
}; };
//Atom::Atom(const File& f, const string& id) //Atom::Atom(const File& f, const string& id)
...@@ -642,25 +642,25 @@ void Atom::location(Point p) ...@@ -642,25 +642,25 @@ void Atom::location(Point p)
impl()->moveTo(p); impl()->moveTo(p);
} }
Atom Atom::symmetryCopy(const Point& d, const clipper::RTop_orth& rt) // Atom Atom::symmetryCopy(const Point& d, const clipper::RTop_orth& rt)
{ // {
return Atom(new AtomImpl(*impl(), d, rt)); // return Atom(new AtomImpl(*impl(), d, rt));
} // }
bool Atom::isSymmetryCopy() const // bool Atom::isSymmetryCopy() const
{ // {
return impl()->mSymmetryCopy; // return impl()->mSymmetryCopy;
} // }
string Atom::symmetry() const // string Atom::symmetry() const
{ // {
return clipper::Symop(impl()->mRTop).format() + "\n" + impl()->mRTop.format(); // return clipper::Symop(impl()->mRTop).format() + "\n" + impl()->mRTop.format();
} // }
const clipper::RTop_orth& Atom::symop() const // const clipper::RTop_orth& Atom::symop() const
{ // {
return impl()->mRTop; // return impl()->mRTop;
} // }
const Compound& Atom::comp() const const Compound& Atom::comp() const
{ {
...@@ -678,20 +678,20 @@ bool Atom::operator==(const Atom& rhs) const ...@@ -678,20 +678,20 @@ bool Atom::operator==(const Atom& rhs) const
(&impl()->mFile == &rhs.impl()->mFile and impl()->mID == rhs.impl()->mID); (&impl()->mFile == &rhs.impl()->mFile and impl()->mID == rhs.impl()->mID);
} }
clipper::Atom Atom::toClipper() const // clipper::Atom Atom::toClipper() const
{ // {
return impl()->toClipper(); // return impl()->toClipper();
} // }
void Atom::calculateRadius(float resHigh, float resLow, float perc) // void Atom::calculateRadius(float resHigh, float resLow, float perc)
{ // {
AtomShape shape(*this, resHigh, resLow, false); // AtomShape shape(*this, resHigh, resLow, false);
impl()->mRadius = shape.radius(); // impl()->mRadius = shape.radius();
// verbose // // verbose
if (cif::VERBOSE > 1) // if (cif::VERBOSE > 1)
cout << "Calculated radius for " << AtomTypeTraits(impl()->mType).name() << " with charge " << charge() << " is " << impl()->mRadius << endl; // cout << "Calculated radius for " << AtomTypeTraits(impl()->mType).name() << " with charge " << charge() << " is " << impl()->mRadius << endl;
} // }
float Atom::radius() const float Atom::radius() const
{ {
......
...@@ -38,197 +38,13 @@ namespace mmcif ...@@ -38,197 +38,13 @@ namespace mmcif
{ {
// -------------------------------------------------------------------- // --------------------------------------------------------------------
clipper::Coord_orth CalculateOffsetForCell(const Structure& p, const clipper::Spacegroup& spacegroup, const clipper::Cell& cell)
{
auto& atoms = p.atoms();
size_t dim = atoms.size();
vector<clipper::Coord_orth> locations;
locations.reserve(dim);
// bounding box
Point pMin(numeric_limits<float>::max(), numeric_limits<float>::max(), numeric_limits<float>::max()),
pMax(numeric_limits<float>::min(), numeric_limits<float>::min(), numeric_limits<float>::min());
for (auto& atom: atoms)
{
auto p = atom.location();
locations.push_back(p);
if (pMin.mX > p.mX)
pMin.mX = p.mX;
if (pMin.mY > p.mY)
pMin.mY = p.mY;
if (pMin.mZ > p.mZ)
pMin.mZ = p.mZ;
if (pMax.mX < p.mX)
pMax.mX = p.mX;
if (pMax.mY < p.mY)
pMax.mY = p.mY;
if (pMax.mZ < p.mZ)
pMax.mZ = p.mZ;
};
// correct locations so that the median of x, y and z are inside the cell
vector<float> c(dim);
auto median = [&]()
{
return dim % 1 == 0
? c[dim / 2]
: (c[dim / 2 - 1] + c[dim / 2]) / 2;
};
transform(locations.begin(), locations.end(), c.begin(), [](auto& l) { return l[0]; });
sort(c.begin(), c.end());
float mx = median();
transform(locations.begin(), locations.end(), c.begin(), [](auto& l) { return l[1]; });
sort(c.begin(), c.end());
float my = median();
transform(locations.begin(), locations.end(), c.begin(), [](auto& l) { return l[2]; });
sort(c.begin(), c.end());
float mz = median();
if (cif::VERBOSE > 1)
cerr << "median position of atoms: " << Point(mx, my, mz) << endl;
auto calculateD = [&](float m, float c)
{
float d = 0;
assert(c != 0);
if (c != 0)
{
while (m + d < -(c / 2))
d += c;
while (m + d > (c / 2))
d -= c;
}
return d;
};
if (cell.a() == 0 or cell.b() == 0 or cell.c() == 0)
throw runtime_error("Invalid cell, contains a dimension that is zero");
Point D;
D.mX = calculateD(mx, cell.a());
D.mY = calculateD(my, cell.b());
D.mZ = calculateD(mz, cell.c());
if (D.mX != 0 or D.mY != 0 or D.mZ != 0)
{
if (cif::VERBOSE)
cerr << "moving coorinates by " << D.mX << ", " << D.mY << " and " << D.mZ << endl;
}
return D;
}
// --------------------------------------------------------------------
vector<clipper::RTop_orth> AlternativeSites(const clipper::Spacegroup& spacegroup,
const clipper::Cell& cell)
{
vector<clipper::RTop_orth> result;
// to make the operation at index 0 equal to identity
result.push_back(clipper::RTop_orth::identity());
for (int i = 0; i < spacegroup.num_symops(); ++i)
{
const auto& symop = spacegroup.symop(i);
for (int u: { -1, 0, 1})
for (int v: { -1, 0, 1})
for (int w: { -1, 0, 1})
{
if (i == 0 and u == 0 and v == 0 and w == 0)
continue;
auto rtop = clipper::RTop_frac(
symop.rot(), symop.trn() + clipper::Vec3<>(u, v, w)
).rtop_orth(cell);
result.push_back(move(rtop));
}
}
return result;
}
// --------------------------------------------------------------------
// Unfortunately, clipper has a different numbering scheme than PDB // Unfortunately, clipper has a different numbering scheme than PDB
// for rotation numbers. So we created a table to map those. // for rotation numbers. So we created a table to map those.
// Perhaps a bit over the top, but hey.... // Perhaps a bit over the top, but hey....
#include "SymOpTable_data.cpp" #include "SymOpTable_data.cpp"
int32_t GetRotationalIndexNumber(int spacegroup, const clipper::RTop_frac& rt)
{
auto& rot = rt.rot();
auto& trn = rt.trn();
auto rte = [&rot](int i, int j) { return static_cast<int8_t>(lrint(rot(i, j))); };
SymopData k
{
{
rte(0, 0), rte(0, 1), rte(0, 2),
rte(1, 0), rte(1, 1), rte(1, 2),
rte(2, 0), rte(2, 1), rte(2, 2)
}
};
for (int i = 0; i < 3; ++i)
{
int n = lrint(trn[i] * 24);
int d = 24;
if (n == 0 or abs(n) == 24)
continue; // is 0, 0 in our table
for (int i = 5; i > 1; --i)
if (n % i == 0 and d % i == 0)
{
n /= i;
d /= i;
}
n = (n + d) % d;
switch (i)
{
case 0: k.trn_0_0 = n; k.trn_0_1 = d; break;
case 1: k.trn_1_0 = n; k.trn_1_1 = d; break;
case 2: k.trn_2_0 = n; k.trn_2_1 = d; break;
}
}
const size_t N = sizeof(kSymopNrTable) / sizeof(SymopDataBlock);
int32_t L = 0, R = static_cast<int32_t>(N - 1);
while (L <= R)
{
int32_t i = (L + R) / 2;
if (kSymopNrTable[i].spacegroupNr < spacegroup)
L = i + 1;
else
R = i - 1;
}
for (size_t i = L; i < N and kSymopNrTable[i].spacegroupNr == spacegroup; ++i)
{
if (kSymopNrTable[i].rt.iv == k.iv)
return kSymopNrTable[i].rotationalNr;
}
throw runtime_error("Symmetry operation was not found in table, cannot find rotational number");
}
// -------------------------------------------------------------------- // --------------------------------------------------------------------
// And unfortunately, clipper does not know all the spacegroup names mentioned in symop.lib
int GetSpacegroupNumber(std::string spacegroup) int GetSpacegroupNumber(std::string spacegroup)
{ {
...@@ -277,141 +93,4 @@ int GetSpacegroupNumber(std::string spacegroup) ...@@ -277,141 +93,4 @@ int GetSpacegroupNumber(std::string spacegroup)
return result; return result;
} }
// -----------------------------------------------------------------------
std::string SpacegroupToHall(std::string spacegroup)
{
int nr = GetSpacegroupNumber(spacegroup);
// yeah, sucks, I know, might be looping three times this way
string result;
for (auto& sp: kSpaceGroups)
{
if (sp.nr == nr)
{
result = sp.Hall;
break;
}
}
if (result.empty())
throw runtime_error("Spacegroup name " + spacegroup + " was not found in table");
return result;
}
// clipper::Spgr_descr GetCCP4SpacegroupDescr(int nr)
// {
// const size_t N = sizeof(kSymopNrTable) / sizeof(SymopDataBlock);
// int32_t L = 0, R = static_cast<int32_t>(N - 1);
// while (L <= R)
// {
// int32_t i = (L + R) / 2;
// if (kSymopNrTable[i].spacegroupNr < nr)
// L = i + 1;
// else
// R = i - 1;
// }
// if (L < 0 or L >= N)
// throw runtime_error("Invalid spacegroup number");
// clipper::Spgr_descr::Symop_codes symop_codes;
// for (size_t i = L; i < N and kSymopNrTable[i].spacegroupNr == nr; ++i)
// {
// auto& symop = kSymopNrTable[i];
// clipper::ftype m[4][4] = {
// { symop.rt.rot_0_0, symop.rt.rot_0_1, symop.rt.rot_0_2, static_cast<float>(symop.rt.trn_0_0) / symop.rt.trn_0_1 },
// { symop.rt.rot_1_0, symop.rt.rot_1_1, symop.rt.rot_1_2, static_cast<float>(symop.rt.trn_1_0) / symop.rt.trn_1_1 },
// { symop.rt.rot_2_0, symop.rt.rot_2_1, symop.rt.rot_2_2, static_cast<float>(symop.rt.trn_2_0) / symop.rt.trn_2_1 },
// { 0, 0, 0, 1 }
// };
// symop_codes.emplace_back(clipper::Symop(m));
// }
// return clipper::Spgr_descr(symop_codes);
// }
clipper::Spgr_descr GetCCP4SpacegroupDescr(int nr)
{
for (auto& sg: kSpaceGroups)
{
if (sg.nr == nr)
return clipper::Spgr_descr(sg.Hall, clipper::Spgr_descr::Hall);
}
throw runtime_error("Invalid spacegroup number: " + to_string(nr));
}
// -----------------------------------------------------------------------
SymmetryAtomIteratorFactory::SymmetryAtomIteratorFactory(const Structure& p, int spacegroupNr, const clipper::Cell& cell)
: mSpacegroupNr(spacegroupNr)
, mSpacegroup(GetCCP4SpacegroupDescr(spacegroupNr))
, mD(CalculateOffsetForCell(p, mSpacegroup, cell))
, mRtOrth(AlternativeSites(mSpacegroup, cell))
, mCell(cell)
{
}
string SymmetryAtomIteratorFactory::symop_mmcif(const Atom& a) const
{
string result;
if (not a.isSymmetryCopy())
result = "1_555";
else
{
auto rtop_o = a.symop();
for (int i = 0; i < mSpacegroup.num_symops(); ++i)
{
const auto& symop = mSpacegroup.symop(i);
for (int u: { -1, 0, 1})
for (int v: { -1, 0, 1})
for (int w: { -1, 0, 1})
{
// if (i == 0 and u == 0 and v == 0 and w == 0)
// continue;
auto rtop = clipper::RTop_frac(
symop.rot(), symop.trn() + clipper::Vec3<>(u, v, w)
).rtop_orth(mCell);
if (rtop.rot().equals(rtop_o.rot(), 0.00001) and rtop.trn().equals(rtop_o.trn(), 0.000001))
{
// gotcha
auto rtop_f = rtop.rtop_frac(mCell);
int rnr = GetRotationalIndexNumber(mSpacegroupNr, rtop_f);
uint32_t t[3] = {
static_cast<uint32_t>(5 + static_cast<int>(rint(rtop_f.trn()[0]))),
static_cast<uint32_t>(5 + static_cast<int>(rint(rtop_f.trn()[1]))),
static_cast<uint32_t>(5 + static_cast<int>(rint(rtop_f.trn()[2])))
};
if (t[0] > 9 or t[1] > 9 or t[2] > 9)
throw runtime_error("Symmetry operation has an out-of-range translation.");
result += to_string(rnr) + "_"
+ to_string(t[0])
+ to_string(t[1])
+ to_string(t[2]);
return result;
}
}
}
}
return result;
}
} }
...@@ -27,7 +27,8 @@ ...@@ -27,7 +27,8 @@
#define BOOST_TEST_MODULE LibCifPP_Test #define BOOST_TEST_MODULE LibCifPP_Test
#include <boost/test/included/unit_test.hpp> #include <boost/test/included/unit_test.hpp>
#include "cif++/DistanceMap.hpp" // #include "cif++/DistanceMap.hpp"
#include "cif++/Cif++.hpp"
// -------------------------------------------------------------------- // --------------------------------------------------------------------
...@@ -49,7 +50,7 @@ cif::File operator""_cf(const char* text, size_t length) ...@@ -49,7 +50,7 @@ cif::File operator""_cf(const char* text, size_t length)
BOOST_AUTO_TEST_CASE(ut1) BOOST_AUTO_TEST_CASE(ut1)
{ {
using namespace mmcif; // using namespace mmcif;
auto f = R"(data_TEST auto f = R"(data_TEST
# #
...@@ -88,16 +89,17 @@ _test.name ...@@ -88,16 +89,17 @@ _test.name
BOOST_AUTO_TEST_CASE(ut2) BOOST_AUTO_TEST_CASE(ut2)
{ {
using namespace mmcif; // using namespace mmcif;
auto f = R"(data_TEST auto f = R"(data_TEST
# #
loop_ loop_
_test.id _test.id
_test.name _test.name
1 aap _test.value
2 noot 1 aap 1.0
3 mies 2 noot 1.1
3 mies 1.2
)"_cf; )"_cf;
auto& db = f.firstDatablock(); auto& db = f.firstDatablock();
...@@ -113,9 +115,14 @@ _test.name ...@@ -113,9 +115,14 @@ _test.name
BOOST_CHECK(++n == 1); BOOST_CHECK(++n == 1);
BOOST_CHECK(r["id"].as<int>() == 1); BOOST_CHECK(r["id"].as<int>() == 1);
BOOST_CHECK(r["name"].as<std::string>() == "aap"); BOOST_CHECK(r["name"].as<std::string>() == "aap");
BOOST_CHECK(r["value"].as<float>() == 1.0);
} }
auto t = test.find(cif::Key("id") == 1); auto t = test.find(cif::Key("id") == 1);
BOOST_CHECK(not t.empty()); BOOST_CHECK(not t.empty());
BOOST_CHECK(t.front()["name"].as<std::string>() == "aap"); BOOST_CHECK(t.front()["name"].as<std::string>() == "aap");
auto t2 = test.find(cif::Key("value") == 1.2);
BOOST_CHECK(not t2.empty());
BOOST_CHECK(t2.front()["name"].as<std::string>() == "mies");
} }
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment