mirror of
https://github.com/PDB-REDO/libcifpp.git
synced 2026-06-05 23:04:29 +08:00
Compare commits
63 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
24aa7a70e5 | ||
|
|
5ade3d6cdd | ||
|
|
0d8e548ffc | ||
|
|
b09650812f | ||
|
|
acc9ad5c08 | ||
|
|
67b6c4bd27 | ||
|
|
7a1d3dbdfa | ||
|
|
4bf10df0c5 | ||
|
|
d84faad109 | ||
|
|
e01ace7ea4 | ||
|
|
e004e1591e | ||
|
|
4613084e1b | ||
|
|
637b795a8f | ||
|
|
4de981a3c0 | ||
|
|
15db026e27 | ||
|
|
d88d520553 | ||
|
|
46cd98ea1d | ||
|
|
d10328d891 | ||
|
|
e418a17256 | ||
|
|
627d3b9df2 | ||
|
|
ba28ade414 | ||
|
|
7c11130357 | ||
|
|
151915beea | ||
|
|
4f9aacb338 | ||
|
|
1f8e491ddc | ||
|
|
05cfa92182 | ||
|
|
e8031aeb49 | ||
|
|
85885406aa | ||
|
|
636f17d78d | ||
|
|
29559a5339 | ||
|
|
19f2fd75c9 | ||
|
|
8a60bae335 | ||
|
|
fa5ff60550 | ||
|
|
f6e0568964 | ||
|
|
fa27a11fea | ||
|
|
19706559cb | ||
|
|
0a06a0a51d | ||
|
|
b045177734 | ||
|
|
7ee5fa8765 | ||
|
|
3e690048a6 | ||
|
|
7ec3bfea9f | ||
|
|
098f3fd496 | ||
|
|
5476eef049 | ||
|
|
33c1eea9a1 | ||
|
|
d3432ed87c | ||
|
|
f05363ea93 | ||
|
|
77389c20a4 | ||
|
|
7c5f1ba85e | ||
|
|
e7c34cc15c | ||
|
|
72fd03a6b2 | ||
|
|
61f464ae4d | ||
|
|
19cdf66f10 | ||
|
|
0c036df6a8 | ||
|
|
4c1b9d83d1 | ||
|
|
b976b4657b | ||
|
|
eba04950d5 | ||
|
|
0c70df27ec | ||
|
|
d83f34722b | ||
|
|
652b6021d3 | ||
|
|
7fe9c87b6e | ||
|
|
9b2ae6d7fd | ||
|
|
8fd5b9a34b | ||
|
|
dffbf52d04 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -7,3 +7,4 @@ CMakeSettings.json
|
||||
msvc/
|
||||
src/revision.hpp
|
||||
test/test-create_sugar_?.cif
|
||||
Testing/
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
# set the project name
|
||||
project(cifpp VERSION 5.0.5 LANGUAGES CXX)
|
||||
project(cifpp VERSION 5.0.8 LANGUAGES CXX)
|
||||
|
||||
list(PREPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
|
||||
|
||||
@@ -35,10 +35,13 @@ include(CheckIncludeFiles)
|
||||
include(CheckLibraryExists)
|
||||
include(CMakePackageConfigHelpers)
|
||||
include(CheckCXXSourceCompiles)
|
||||
include(GenerateExportHeader)
|
||||
|
||||
set(CXX_EXTENSIONS OFF)
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
# set(CMAKE_CXX_VISIBILITY_PRESET hidden)
|
||||
# set(CMAKE_VISIBILITY_INLINES_HIDDEN 1)
|
||||
|
||||
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wno-unused-parameter -Wno-missing-field-initializers")
|
||||
@@ -86,6 +89,7 @@ if(BUILD_FOR_CCP4)
|
||||
list(APPEND CMAKE_MODULE_PATH "$ENV{CCP4}")
|
||||
list(APPEND CMAKE_PREFIX_PATH "$ENV{CCP4}")
|
||||
set(CMAKE_INSTALL_PREFIX "$ENV{CCP4}")
|
||||
set(CMAKE_INSTALL_FULL_DATADIR "${CMAKE_INSTALL_PREFIX}/share/libcifpp")
|
||||
|
||||
if(WIN32)
|
||||
set(BUILD_SHARED_LIBS ON)
|
||||
@@ -170,6 +174,12 @@ list(APPEND CIFPP_REQUIRED_LIBRARIES ${STDCPPFS_LIBRARY})
|
||||
include(FindAtomic)
|
||||
list(APPEND CIFPP_REQUIRED_LIBRARIES ${STDCPPATOMIC_LIBRARY})
|
||||
|
||||
if(MSVC)
|
||||
# this dependency can go once MSVC supports std::experimental::is_detected
|
||||
find_package(zeep 5.1.8 REQUIRED)
|
||||
list(APPEND CIFPP_REQUIRED_LIBRARIES zeep::zeep)
|
||||
endif()
|
||||
|
||||
# Create a revision file, containing the current git version info
|
||||
include(VersionString)
|
||||
write_version_header(${PROJECT_SOURCE_DIR}/src/ "LibCIFPP")
|
||||
@@ -224,7 +234,6 @@ set(project_headers
|
||||
${PROJECT_SOURCE_DIR}/include/cif++/datablock.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/cif++/file.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/cif++/validate.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/cif++/list.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/cif++/iterator.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/cif++/parser.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/cif++/forward_decl.hpp
|
||||
@@ -249,6 +258,7 @@ set(project_headers
|
||||
|
||||
add_library(cifpp ${project_sources} ${project_headers} ${PROJECT_SOURCE_DIR}/src/symop_table_data.hpp)
|
||||
add_library(cifpp::cifpp ALIAS cifpp)
|
||||
generate_export_header(cifpp EXPORT_FILE_NAME cif++/exports.hpp)
|
||||
|
||||
if(BOOST_REGEX)
|
||||
target_compile_definitions(cifpp PRIVATE USE_BOOST_REGEX=1 BOOST_REGEX_STANDALONE=1)
|
||||
@@ -263,7 +273,7 @@ set_target_properties(cifpp PROPERTIES POSITION_INDEPENDENT_CODE ON)
|
||||
|
||||
target_include_directories(cifpp
|
||||
PUBLIC
|
||||
"$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>"
|
||||
"$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include;${PROJECT_BINARY_DIR}>"
|
||||
"$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>"
|
||||
)
|
||||
|
||||
@@ -343,6 +353,12 @@ install(
|
||||
COMPONENT Devel
|
||||
)
|
||||
|
||||
install(
|
||||
FILES ${PROJECT_BINARY_DIR}/cif++/exports.hpp
|
||||
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/cif++
|
||||
COMPONENT Devel
|
||||
)
|
||||
|
||||
install(FILES
|
||||
${PROJECT_SOURCE_DIR}/rsrc/mmcif_ddl.dic
|
||||
${PROJECT_SOURCE_DIR}/rsrc/mmcif_pdbx.dic
|
||||
|
||||
17
changelog
17
changelog
@@ -1,3 +1,20 @@
|
||||
Version 5.0.8
|
||||
- implemented find_first, find_min, find_max and count in category
|
||||
- find1 now throws an exception if condition does not not exactly match one row
|
||||
- Change in writing out PDB files, now looking up the original auth_seq_num
|
||||
via the pdbx_xxx_scheme categories based on the atom_site.auth_seq_num ->
|
||||
pdbx_xxx_scheme.pdb_seq_num relationship.
|
||||
|
||||
Version 5.0.7.1
|
||||
- Use the implementation from zeep for std::experimental::is_detected
|
||||
|
||||
Version 5.0.7
|
||||
- Reintroduce exports file. For DLL's
|
||||
|
||||
Version 5.0.6
|
||||
- Fix file::contains, using iequals
|
||||
- Fix is_cis
|
||||
|
||||
Version 5.0.5
|
||||
- Fix code to work on 32 bit machines
|
||||
|
||||
|
||||
@@ -5,6 +5,10 @@ find_dependency(Threads)
|
||||
|
||||
find_dependency(ZLIB REQUIRED)
|
||||
|
||||
if(MSVC)
|
||||
find_dependency(zeep REQUIRED)
|
||||
endif()
|
||||
|
||||
INCLUDE("${CMAKE_CURRENT_LIST_DIR}/cifppTargets.cmake")
|
||||
|
||||
set_and_check(CIFPP_SHARE_DIR "@PACKAGE_CIFPP_DATA_DIR@")
|
||||
|
||||
@@ -204,7 +204,7 @@ struct atom_type_info
|
||||
float radii[kRadiusTypeCount];
|
||||
};
|
||||
|
||||
extern const atom_type_info kKnownAtoms[];
|
||||
extern CIFPP_EXPORT const atom_type_info kKnownAtoms[];
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// AtomTypeTraits
|
||||
|
||||
@@ -26,8 +26,6 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
|
||||
#include <cif++/forward_decl.hpp>
|
||||
|
||||
#include <cif++/condition.hpp>
|
||||
@@ -35,6 +33,8 @@
|
||||
#include <cif++/row.hpp>
|
||||
#include <cif++/validate.hpp>
|
||||
|
||||
#include <array>
|
||||
|
||||
// TODO: implement all of:
|
||||
// https://en.cppreference.com/w/cpp/named_req/Container
|
||||
// https://en.cppreference.com/w/cpp/named_req/SequenceContainer
|
||||
@@ -49,7 +49,18 @@ class duplicate_key_error : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
duplicate_key_error(const std::string &msg)
|
||||
: std::runtime_error(msg) {}
|
||||
: std::runtime_error(msg)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
class multiple_results_error : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
multiple_results_error()
|
||||
: std::runtime_error("query should have returned exactly one row")
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
@@ -109,52 +120,52 @@ class category
|
||||
|
||||
reference front()
|
||||
{
|
||||
return {*this, *m_head};
|
||||
return { *this, *m_head };
|
||||
}
|
||||
|
||||
const_reference front() const
|
||||
{
|
||||
return {const_cast<category &>(*this), const_cast<row &>(*m_head)};
|
||||
return { const_cast<category &>(*this), const_cast<row &>(*m_head) };
|
||||
}
|
||||
|
||||
reference back()
|
||||
{
|
||||
return {*this, *m_tail};
|
||||
return { *this, *m_tail };
|
||||
}
|
||||
|
||||
const_reference back() const
|
||||
{
|
||||
return {const_cast<category &>(*this), const_cast<row &>(*m_tail)};
|
||||
return { const_cast<category &>(*this), const_cast<row &>(*m_tail) };
|
||||
}
|
||||
|
||||
iterator begin()
|
||||
{
|
||||
return {*this, m_head};
|
||||
return { *this, m_head };
|
||||
}
|
||||
|
||||
iterator end()
|
||||
{
|
||||
return {*this, nullptr};
|
||||
return { *this, nullptr };
|
||||
}
|
||||
|
||||
const_iterator begin() const
|
||||
{
|
||||
return {*this, m_head};
|
||||
return { *this, m_head };
|
||||
}
|
||||
|
||||
const_iterator end() const
|
||||
{
|
||||
return {*this, nullptr};
|
||||
return { *this, nullptr };
|
||||
}
|
||||
|
||||
const_iterator cbegin() const
|
||||
{
|
||||
return {*this, m_head};
|
||||
return { *this, m_head };
|
||||
}
|
||||
|
||||
const_iterator cend() const
|
||||
{
|
||||
return {*this, nullptr};
|
||||
return { *this, nullptr };
|
||||
}
|
||||
|
||||
size_t size() const
|
||||
@@ -189,64 +200,64 @@ class category
|
||||
iterator_proxy<const category, Ts...> rows(Ns... names) const
|
||||
{
|
||||
static_assert(sizeof...(Ts) == sizeof...(Ns), "The number of column titles should be equal to the number of types to return");
|
||||
return iterator_proxy<const category, Ts...>(*this, begin(), {names...});
|
||||
return iterator_proxy<const category, Ts...>(*this, begin(), { names... });
|
||||
}
|
||||
|
||||
template <typename... Ts, typename... Ns>
|
||||
iterator_proxy<category, Ts...> rows(Ns... names)
|
||||
{
|
||||
static_assert(sizeof...(Ts) == sizeof...(Ns), "The number of column titles should be equal to the number of types to return");
|
||||
return iterator_proxy<category, Ts...>(*this, begin(), {names...});
|
||||
return iterator_proxy<category, Ts...>(*this, begin(), { names... });
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
conditional_iterator_proxy<category> find(condition &&cond)
|
||||
{
|
||||
return find(begin(), std::forward<condition>(cond));
|
||||
return find(begin(), std::move(cond));
|
||||
}
|
||||
|
||||
conditional_iterator_proxy<category> find(iterator pos, condition &&cond)
|
||||
{
|
||||
return {*this, pos, std::forward<condition>(cond)};
|
||||
return { *this, pos, std::move(cond) };
|
||||
}
|
||||
|
||||
conditional_iterator_proxy<const category> find(condition &&cond) const
|
||||
{
|
||||
return find(cbegin(), std::forward<condition>(cond));
|
||||
return find(cbegin(), std::move(cond));
|
||||
}
|
||||
|
||||
conditional_iterator_proxy<const category> find(const_iterator pos, condition &&cond) const
|
||||
{
|
||||
return conditional_iterator_proxy<const category>{*this, pos, std::forward<condition>(cond)};
|
||||
return conditional_iterator_proxy<const category>{ *this, pos, std::move(cond) };
|
||||
}
|
||||
|
||||
template <typename... Ts, typename... Ns>
|
||||
conditional_iterator_proxy<category, Ts...> find(condition &&cond, Ns... names)
|
||||
{
|
||||
static_assert(sizeof...(Ts) == sizeof...(Ns), "The number of column titles should be equal to the number of types to return");
|
||||
return find<Ts...>(cbegin(), std::forward<condition>(cond), std::forward<Ns>(names)...);
|
||||
return find<Ts...>(cbegin(), std::move(cond), std::forward<Ns>(names)...);
|
||||
}
|
||||
|
||||
template <typename... Ts, typename... Ns>
|
||||
conditional_iterator_proxy<const category, Ts...> find(condition &&cond, Ns... names) const
|
||||
{
|
||||
static_assert(sizeof...(Ts) == sizeof...(Ns), "The number of column titles should be equal to the number of types to return");
|
||||
return find<Ts...>(cbegin(), std::forward<condition>(cond), std::forward<Ns>(names)...);
|
||||
return find<Ts...>(cbegin(), std::move(cond), std::forward<Ns>(names)...);
|
||||
}
|
||||
|
||||
template <typename... Ts, typename... Ns>
|
||||
conditional_iterator_proxy<category, Ts...> find(const_iterator pos, condition &&cond, Ns... names)
|
||||
{
|
||||
static_assert(sizeof...(Ts) == sizeof...(Ns), "The number of column titles should be equal to the number of types to return");
|
||||
return {*this, pos, std::forward<condition>(cond), std::forward<Ns>(names)...};
|
||||
return { *this, pos, std::move(cond), std::forward<Ns>(names)... };
|
||||
}
|
||||
|
||||
template <typename... Ts, typename... Ns>
|
||||
conditional_iterator_proxy<const category, Ts...> find(const_iterator pos, condition &&cond, Ns... names) const
|
||||
{
|
||||
static_assert(sizeof...(Ts) == sizeof...(Ns), "The number of column titles should be equal to the number of types to return");
|
||||
return {*this, pos, std::forward<condition>(cond), std::forward<Ns>(names)...};
|
||||
return { *this, pos, std::move(cond), std::forward<Ns>(names)... };
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
@@ -254,40 +265,49 @@ class category
|
||||
|
||||
row_handle find1(condition &&cond)
|
||||
{
|
||||
return find1(begin(), std::forward<condition>(cond));
|
||||
return find1(begin(), std::move(cond));
|
||||
}
|
||||
|
||||
row_handle find1(iterator pos, condition &&cond)
|
||||
{
|
||||
auto h = find(pos, std::forward<condition>(cond));
|
||||
auto h = find(pos, std::move(cond));
|
||||
|
||||
return h.size() != 1 ? row_handle{} : *h.begin();
|
||||
if (h.size() != 1)
|
||||
throw multiple_results_error();
|
||||
|
||||
return *h.begin();
|
||||
}
|
||||
|
||||
const row_handle find1(condition &&cond) const
|
||||
{
|
||||
return find1(cbegin(), std::forward<condition>(cond));
|
||||
return find1(cbegin(), std::move(cond));
|
||||
}
|
||||
|
||||
const row_handle find1(const_iterator pos, condition &&cond) const
|
||||
{
|
||||
auto h = find(pos, std::forward<condition>(cond));
|
||||
auto h = find(pos, std::move(cond));
|
||||
|
||||
return h.size() != 1 ? row_handle{} : *h.begin();
|
||||
if (h.size() != 1)
|
||||
throw multiple_results_error();
|
||||
|
||||
return *h.begin();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T find1(condition &&cond, const char *column) const
|
||||
{
|
||||
return find1<T>(cbegin(), std::forward<condition>(cond), column);
|
||||
return find1<T>(cbegin(), std::move(cond), column);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T find1(const_iterator pos, condition &&cond, const char *column) const
|
||||
{
|
||||
auto h = find<T>(pos, std::forward<condition>(cond), column);
|
||||
auto h = find<T>(pos, std::move(cond), column);
|
||||
|
||||
return h.size() == 1 ? *h.begin() : T{};
|
||||
if (h.size() != 1)
|
||||
throw multiple_results_error();
|
||||
|
||||
return *h.begin();
|
||||
}
|
||||
|
||||
template <typename... Ts, typename... Cs, typename U = std::enable_if_t<sizeof...(Ts) != 1>>
|
||||
@@ -295,16 +315,119 @@ class category
|
||||
{
|
||||
static_assert(sizeof...(Ts) == sizeof...(Cs), "The number of column titles should be equal to the number of types to return");
|
||||
// static_assert(std::is_same_v<Cs, const char*>..., "The column names should be const char");
|
||||
return find1<Ts...>(cbegin(), std::forward<condition>(cond), std::forward<Cs>(columns)...);
|
||||
return find1<Ts...>(cbegin(), std::move(cond), std::forward<Cs>(columns)...);
|
||||
}
|
||||
|
||||
template <typename... Ts, typename... Cs, typename U = std::enable_if_t<sizeof...(Ts) != 1>>
|
||||
std::tuple<Ts...> find1(const_iterator pos, condition &&cond, Cs... columns) const
|
||||
{
|
||||
static_assert(sizeof...(Ts) == sizeof...(Cs), "The number of column titles should be equal to the number of types to return");
|
||||
auto h = find<Ts...>(pos, std::forward<condition>(cond), std::forward<Cs>(columns)...);
|
||||
auto h = find<Ts...>(pos, std::move(cond), std::forward<Cs>(columns)...);
|
||||
|
||||
return h.size() == 1 ? *h.begin() : std::tuple<Ts...>{};
|
||||
if (h.size() != 1)
|
||||
throw multiple_results_error();
|
||||
|
||||
return *h.begin();
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// if you want only a first hit
|
||||
|
||||
row_handle find_first(condition &&cond)
|
||||
{
|
||||
return find_first(begin(), std::move(cond));
|
||||
}
|
||||
|
||||
row_handle find_first(iterator pos, condition &&cond)
|
||||
{
|
||||
auto h = find(pos, std::move(cond));
|
||||
|
||||
return h.empty() ? row_handle{} : *h.begin();
|
||||
}
|
||||
|
||||
const row_handle find_first(condition &&cond) const
|
||||
{
|
||||
return find_first(cbegin(), std::move(cond));
|
||||
}
|
||||
|
||||
const row_handle find_first(const_iterator pos, condition &&cond) const
|
||||
{
|
||||
auto h = find(pos, std::move(cond));
|
||||
|
||||
return h.empty() ? row_handle{} : *h.begin();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T find_first(condition &&cond, const char *column) const
|
||||
{
|
||||
return find_first<T>(cbegin(), std::move(cond), column);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T find_first(const_iterator pos, condition &&cond, const char *column) const
|
||||
{
|
||||
auto h = find<T>(pos, std::move(cond), column);
|
||||
|
||||
return h.empty() ? T{} : *h.begin();
|
||||
}
|
||||
|
||||
template <typename... Ts, typename... Cs, typename U = std::enable_if_t<sizeof...(Ts) != 1>>
|
||||
std::tuple<Ts...> find_first(condition &&cond, Cs... columns) const
|
||||
{
|
||||
static_assert(sizeof...(Ts) == sizeof...(Cs), "The number of column titles should be equal to the number of types to return");
|
||||
// static_assert(std::is_same_v<Cs, const char*>..., "The column names should be const char");
|
||||
return find_first<Ts...>(cbegin(), std::move(cond), std::forward<Cs>(columns)...);
|
||||
}
|
||||
|
||||
template <typename... Ts, typename... Cs, typename U = std::enable_if_t<sizeof...(Ts) != 1>>
|
||||
std::tuple<Ts...> find_first(const_iterator pos, condition &&cond, Cs... columns) const
|
||||
{
|
||||
static_assert(sizeof...(Ts) == sizeof...(Cs), "The number of column titles should be equal to the number of types to return");
|
||||
auto h = find<Ts...>(pos, std::move(cond), std::forward<Cs>(columns)...);
|
||||
|
||||
return h.empty() ? std::tuple<Ts...>{} : *h.begin();
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
template <typename T, std::enable_if_t<std::is_arithmetic_v<T>, int> = 0>
|
||||
T find_max(const char *column, condition &&cond) const
|
||||
{
|
||||
T result = std::numeric_limits<T>::min();
|
||||
|
||||
for (auto v : find<T>(std::move(cond), column))
|
||||
{
|
||||
if (result < v)
|
||||
result = v;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename T, std::enable_if_t<std::is_arithmetic_v<T>, int> = 0>
|
||||
T find_max(const char *column) const
|
||||
{
|
||||
return find_max<T>(column, all());
|
||||
}
|
||||
|
||||
template <typename T, std::enable_if_t<std::is_arithmetic_v<T>, int> = 0>
|
||||
T find_min(const char *column, condition &&cond) const
|
||||
{
|
||||
T result = std::numeric_limits<T>::max();
|
||||
|
||||
for (auto v : find<T>(std::move(cond), column))
|
||||
{
|
||||
if (result > v)
|
||||
result = v;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename T, std::enable_if_t<std::is_arithmetic_v<T>, int> = 0>
|
||||
T find_min(const char *column) const
|
||||
{
|
||||
return find_min<T>(column, all());
|
||||
}
|
||||
|
||||
bool exists(condition &&cond) const
|
||||
@@ -335,6 +458,31 @@ class category
|
||||
return result;
|
||||
}
|
||||
|
||||
size_t count(condition &&cond) const
|
||||
{
|
||||
size_t result = 0;
|
||||
|
||||
if (cond)
|
||||
{
|
||||
cond.prepare(*this);
|
||||
|
||||
auto sh = cond.single();
|
||||
|
||||
if (sh.has_value() and *sh)
|
||||
result = 1;
|
||||
else
|
||||
{
|
||||
for (auto r : *this)
|
||||
{
|
||||
if (cond(r))
|
||||
++result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
bool has_children(row_handle r) const;
|
||||
@@ -486,7 +634,7 @@ class category
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
void sort(std::function<int(row_handle,row_handle)> f);
|
||||
void sort(std::function<int(row_handle, row_handle)> f);
|
||||
void reorder_by_index();
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
@@ -583,7 +731,7 @@ class category
|
||||
void swap_item(uint16_t column_ix, row_handle &a, row_handle &b);
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
|
||||
std::string m_name;
|
||||
std::vector<item_column> m_columns;
|
||||
const validator *m_validator = nullptr;
|
||||
|
||||
@@ -29,14 +29,15 @@
|
||||
/// \file This file contains the definition for the class compound, encapsulating
|
||||
/// the information found for compounds in the CCD.
|
||||
|
||||
#include <cif++.hpp>
|
||||
#include <cif++/atom_type.hpp>
|
||||
#include <cif++/point.hpp>
|
||||
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <tuple>
|
||||
#include <vector>
|
||||
|
||||
#include <cif++.hpp>
|
||||
#include <cif++/atom_type.hpp>
|
||||
|
||||
namespace cif
|
||||
{
|
||||
|
||||
@@ -75,6 +76,11 @@ struct compound_atom
|
||||
bool leaving_atom = false;
|
||||
bool stereo_config = false;
|
||||
float x, y, z;
|
||||
|
||||
point get_location() const
|
||||
{
|
||||
return { x, y, z };
|
||||
}
|
||||
};
|
||||
|
||||
/// --------------------------------------------------------------------
|
||||
@@ -114,6 +120,7 @@ class compound
|
||||
compound_atom get_atom_by_atom_id(const std::string &atom_id) const;
|
||||
|
||||
bool atoms_bonded(const std::string &atomId_1, const std::string &atomId_2) const;
|
||||
float bond_length(const std::string &atomId_1, const std::string &atomId_2) const;
|
||||
|
||||
bool is_water() const
|
||||
{
|
||||
@@ -173,7 +180,7 @@ class compound_factory
|
||||
|
||||
~compound_factory();
|
||||
|
||||
static const std::map<std::string, char> kAAMap, kBaseMap;
|
||||
static CIFPP_EXPORT const std::map<std::string, char> kAAMap, kBaseMap;
|
||||
|
||||
private:
|
||||
compound_factory();
|
||||
@@ -188,4 +195,4 @@ class compound_factory
|
||||
std::shared_ptr<compound_factory_impl> m_impl;
|
||||
};
|
||||
|
||||
} // namespace pdbx
|
||||
} // namespace cif
|
||||
|
||||
@@ -26,14 +26,14 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cif++/row.hpp>
|
||||
|
||||
#include <cassert>
|
||||
#include <functional>
|
||||
#include <iostream>
|
||||
#include <regex>
|
||||
#include <utility>
|
||||
|
||||
#include <cif++/row.hpp>
|
||||
|
||||
namespace cif
|
||||
{
|
||||
|
||||
@@ -57,6 +57,8 @@ namespace detail
|
||||
virtual bool test(row_handle) const = 0;
|
||||
virtual void str(std::ostream &) const = 0;
|
||||
virtual std::optional<row_handle> single() const { return {}; };
|
||||
|
||||
virtual bool equals(const condition_impl *rhs) const { return false; }
|
||||
};
|
||||
|
||||
struct all_condition_impl : public condition_impl
|
||||
@@ -145,7 +147,6 @@ class condition
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
void optimise(condition_impl *&impl);
|
||||
|
||||
condition_impl *m_impl;
|
||||
@@ -181,6 +182,33 @@ namespace detail
|
||||
uint16_t m_item_ix = 0;
|
||||
};
|
||||
|
||||
struct key_is_not_empty_condition_impl : public condition_impl
|
||||
{
|
||||
key_is_not_empty_condition_impl(const std::string &item_tag)
|
||||
: m_item_tag(item_tag)
|
||||
{
|
||||
}
|
||||
|
||||
condition_impl *prepare(const category &c) override
|
||||
{
|
||||
m_item_ix = get_column_ix(c, m_item_tag);
|
||||
return this;
|
||||
}
|
||||
|
||||
bool test(row_handle r) const override
|
||||
{
|
||||
return not r[m_item_ix].empty();
|
||||
}
|
||||
|
||||
void str(std::ostream &os) const override
|
||||
{
|
||||
os << m_item_tag << " IS NOT NULL";
|
||||
}
|
||||
|
||||
std::string m_item_tag;
|
||||
uint16_t m_item_ix = 0;
|
||||
};
|
||||
|
||||
struct key_equals_condition_impl : public condition_impl
|
||||
{
|
||||
key_equals_condition_impl(item &&i)
|
||||
@@ -193,9 +221,7 @@ namespace detail
|
||||
|
||||
bool test(row_handle r) const override
|
||||
{
|
||||
return m_single_hit.has_value() ?
|
||||
*m_single_hit == r :
|
||||
r[m_item_ix].compare(m_value, m_icase) == 0;
|
||||
return m_single_hit.has_value() ? *m_single_hit == r : r[m_item_ix].compare(m_value, m_icase) == 0;
|
||||
}
|
||||
|
||||
void str(std::ostream &os) const override
|
||||
@@ -208,6 +234,20 @@ namespace detail
|
||||
return m_single_hit;
|
||||
}
|
||||
|
||||
virtual bool equals(const condition_impl *rhs) const override
|
||||
{
|
||||
if (typeid(*rhs) == typeid(key_equals_condition_impl))
|
||||
{
|
||||
auto ri = static_cast<const key_equals_condition_impl *>(rhs);
|
||||
if (m_single_hit.has_value() or ri->m_single_hit.has_value())
|
||||
return m_single_hit == ri->m_single_hit;
|
||||
else
|
||||
// watch out, both m_item_ix might be the same while tags might be diffent (in case they both do not exist in the category)
|
||||
return m_item_ix == ri->m_item_ix and m_value == ri->m_value and m_item_tag == ri->m_item_tag;
|
||||
}
|
||||
return this == rhs;
|
||||
}
|
||||
|
||||
std::string m_item_tag;
|
||||
uint16_t m_item_ix = 0;
|
||||
bool m_icase = false;
|
||||
@@ -244,7 +284,7 @@ namespace detail
|
||||
|
||||
void str(std::ostream &os) const override
|
||||
{
|
||||
os << m_item_tag << (m_icase ? "^ " : " ") << " == " << m_value << " OR " << m_item_tag << " IS NULL";
|
||||
os << '(' << m_item_tag << (m_icase ? "^ " : " ") << " == " << m_value << " OR " << m_item_tag << " IS NULL)";
|
||||
}
|
||||
|
||||
virtual std::optional<row_handle> single() const override
|
||||
@@ -252,12 +292,26 @@ namespace detail
|
||||
return m_single_hit;
|
||||
}
|
||||
|
||||
virtual bool equals(const condition_impl *rhs) const override
|
||||
{
|
||||
if (typeid(*rhs) == typeid(key_equals_or_empty_condition_impl))
|
||||
{
|
||||
auto ri = static_cast<const key_equals_or_empty_condition_impl *>(rhs);
|
||||
if (m_single_hit.has_value() or ri->m_single_hit.has_value())
|
||||
return m_single_hit == ri->m_single_hit;
|
||||
else
|
||||
// watch out, both m_item_ix might be the same while tags might be diffent (in case they both do not exist in the category)
|
||||
return m_item_ix == ri->m_item_ix and m_value == ri->m_value and m_item_tag == ri->m_item_tag;
|
||||
}
|
||||
return this == rhs;
|
||||
}
|
||||
|
||||
std::string m_item_tag;
|
||||
uint16_t m_item_ix = 0;
|
||||
std::string m_value;
|
||||
bool m_icase = false;
|
||||
std::optional<row_handle> m_single_hit;
|
||||
};
|
||||
};
|
||||
|
||||
struct key_compare_condition_impl : public condition_impl
|
||||
{
|
||||
@@ -409,29 +463,53 @@ namespace detail
|
||||
// case they make up an indexed tuple.
|
||||
struct and_condition_impl : public condition_impl
|
||||
{
|
||||
and_condition_impl() = default;
|
||||
|
||||
and_condition_impl(condition &&a, condition &&b)
|
||||
{
|
||||
mSub.emplace_back(std::exchange(a.m_impl, nullptr));
|
||||
mSub.emplace_back(std::exchange(b.m_impl, nullptr));
|
||||
if (typeid(*a.m_impl) == typeid(*this))
|
||||
{
|
||||
and_condition_impl *ai = static_cast<and_condition_impl *>(a.m_impl);
|
||||
|
||||
std::swap(m_sub, ai->m_sub);
|
||||
m_sub.emplace_back(std::exchange(b.m_impl, nullptr));
|
||||
}
|
||||
else if (typeid(*b.m_impl) == typeid(*this))
|
||||
{
|
||||
and_condition_impl *bi = static_cast<and_condition_impl *>(b.m_impl);
|
||||
|
||||
std::swap(m_sub, bi->m_sub);
|
||||
m_sub.emplace_back(std::exchange(a.m_impl, nullptr));
|
||||
}
|
||||
else
|
||||
{
|
||||
m_sub.emplace_back(std::exchange(a.m_impl, nullptr));
|
||||
m_sub.emplace_back(std::exchange(b.m_impl, nullptr));
|
||||
}
|
||||
}
|
||||
|
||||
~and_condition_impl()
|
||||
{
|
||||
for (auto sub : mSub)
|
||||
for (auto sub : m_sub)
|
||||
delete sub;
|
||||
}
|
||||
|
||||
condition_impl *prepare(const category &c) override;
|
||||
condition_impl *prepare(const category &c) override
|
||||
{
|
||||
for (auto &sub : m_sub)
|
||||
sub = sub->prepare(c);
|
||||
return this;
|
||||
}
|
||||
|
||||
bool test(row_handle r) const override
|
||||
{
|
||||
bool result = true;
|
||||
|
||||
for (auto sub : mSub)
|
||||
for (auto sub : m_sub)
|
||||
{
|
||||
if (sub->test(r))
|
||||
continue;
|
||||
|
||||
|
||||
result = false;
|
||||
break;
|
||||
}
|
||||
@@ -444,7 +522,7 @@ namespace detail
|
||||
os << '(';
|
||||
|
||||
bool first = true;
|
||||
for (auto sub : mSub)
|
||||
for (auto sub : m_sub)
|
||||
{
|
||||
if (first)
|
||||
first = false;
|
||||
@@ -461,7 +539,7 @@ namespace detail
|
||||
{
|
||||
std::optional<row_handle> result;
|
||||
|
||||
for (auto sub : mSub)
|
||||
for (auto sub : m_sub)
|
||||
{
|
||||
auto s = sub->single();
|
||||
|
||||
@@ -470,7 +548,7 @@ namespace detail
|
||||
result = s;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
if (s == result)
|
||||
continue;
|
||||
|
||||
@@ -481,56 +559,100 @@ namespace detail
|
||||
return result;
|
||||
}
|
||||
|
||||
std::vector<condition_impl *> mSub;
|
||||
static condition_impl *combine_equal(std::vector<and_condition_impl *> &subs, or_condition_impl *oc);
|
||||
|
||||
std::vector<condition_impl *> m_sub;
|
||||
};
|
||||
|
||||
struct or_condition_impl : public condition_impl
|
||||
{
|
||||
or_condition_impl(condition &&a, condition &&b)
|
||||
: mA(nullptr)
|
||||
, mB(nullptr)
|
||||
{
|
||||
std::swap(mA, a.m_impl);
|
||||
std::swap(mB, b.m_impl);
|
||||
if (typeid(*a.m_impl) == typeid(*this))
|
||||
{
|
||||
or_condition_impl *ai = static_cast<or_condition_impl *>(a.m_impl);
|
||||
|
||||
std::swap(m_sub, ai->m_sub);
|
||||
m_sub.emplace_back(std::exchange(b.m_impl, nullptr));
|
||||
}
|
||||
else if (typeid(*b.m_impl) == typeid(*this))
|
||||
{
|
||||
or_condition_impl *bi = static_cast<or_condition_impl *>(b.m_impl);
|
||||
|
||||
std::swap(m_sub, bi->m_sub);
|
||||
m_sub.emplace_back(std::exchange(a.m_impl, nullptr));
|
||||
}
|
||||
else
|
||||
{
|
||||
m_sub.emplace_back(std::exchange(a.m_impl, nullptr));
|
||||
m_sub.emplace_back(std::exchange(b.m_impl, nullptr));
|
||||
}
|
||||
}
|
||||
|
||||
~or_condition_impl()
|
||||
{
|
||||
delete mA;
|
||||
delete mB;
|
||||
for (auto sub : m_sub)
|
||||
delete sub;
|
||||
}
|
||||
|
||||
condition_impl *prepare(const category &c) override;
|
||||
|
||||
bool test(row_handle r) const override
|
||||
{
|
||||
return mA->test(r) or mB->test(r);
|
||||
bool result = false;
|
||||
|
||||
for (auto sub : m_sub)
|
||||
{
|
||||
if (not sub->test(r))
|
||||
continue;
|
||||
result = true;
|
||||
break;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void str(std::ostream &os) const override
|
||||
{
|
||||
bool first = true;
|
||||
|
||||
os << '(';
|
||||
mA->str(os);
|
||||
os << ") OR (";
|
||||
mB->str(os);
|
||||
for (auto sub : m_sub)
|
||||
{
|
||||
if (first)
|
||||
first = false;
|
||||
else
|
||||
os << " OR ";
|
||||
sub->str(os);
|
||||
}
|
||||
os << ')';
|
||||
}
|
||||
|
||||
virtual std::optional<row_handle> single() const override
|
||||
{
|
||||
auto sa = mA->single();
|
||||
auto sb = mB->single();
|
||||
|
||||
if (sa.has_value() and sb.has_value() and sa != sb)
|
||||
sa.reset();
|
||||
else if (not sa.has_value())
|
||||
sa = sb;
|
||||
std::optional<row_handle> result;
|
||||
|
||||
return sa;
|
||||
for (auto sub : m_sub)
|
||||
{
|
||||
auto s = sub->single();
|
||||
|
||||
if (not result.has_value())
|
||||
{
|
||||
result = s;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (s == result)
|
||||
continue;
|
||||
|
||||
result.reset();
|
||||
break;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
condition_impl *mA;
|
||||
condition_impl *mB;
|
||||
std::vector<condition_impl *> m_sub;
|
||||
};
|
||||
|
||||
struct not_condition_impl : public condition_impl
|
||||
@@ -569,7 +691,7 @@ namespace detail
|
||||
|
||||
} // namespace detail
|
||||
|
||||
inline condition operator&&(condition &&a, condition &&b)
|
||||
inline condition operator and(condition &&a, condition &&b)
|
||||
{
|
||||
if (a.m_impl and b.m_impl)
|
||||
return condition(new detail::and_condition_impl(std::move(a), std::move(b)));
|
||||
@@ -578,12 +700,35 @@ inline condition operator&&(condition &&a, condition &&b)
|
||||
return condition(std::move(b));
|
||||
}
|
||||
|
||||
inline condition operator||(condition &&a, condition &&b)
|
||||
inline condition operator or(condition &&a, condition &&b)
|
||||
{
|
||||
if (a.m_impl and b.m_impl)
|
||||
{
|
||||
if (typeid(*a.m_impl) == typeid(detail::key_equals_condition_impl) and
|
||||
typeid(*b.m_impl) == typeid(detail::key_is_empty_condition_impl))
|
||||
{
|
||||
auto ci = static_cast<detail::key_equals_condition_impl *>(a.m_impl);
|
||||
auto ce = static_cast<detail::key_is_empty_condition_impl *>(b.m_impl);
|
||||
|
||||
if (ci->m_item_tag == ce->m_item_tag)
|
||||
return condition(new detail::key_equals_or_empty_condition_impl(ci));
|
||||
}
|
||||
else if (typeid(*b.m_impl) == typeid(detail::key_equals_condition_impl) and
|
||||
typeid(*a.m_impl) == typeid(detail::key_is_empty_condition_impl))
|
||||
{
|
||||
auto ci = static_cast<detail::key_equals_condition_impl *>(b.m_impl);
|
||||
auto ce = static_cast<detail::key_is_empty_condition_impl *>(a.m_impl);
|
||||
|
||||
if (ci->m_item_tag == ce->m_item_tag)
|
||||
return condition(new detail::key_equals_or_empty_condition_impl(ci));
|
||||
}
|
||||
|
||||
return condition(new detail::or_condition_impl(std::move(a), std::move(b)));
|
||||
}
|
||||
|
||||
if (a.m_impl)
|
||||
return condition(std::move(a));
|
||||
|
||||
return condition(std::move(b));
|
||||
}
|
||||
|
||||
@@ -706,7 +851,12 @@ inline condition operator==(const key &key, const empty_type &)
|
||||
return condition(new detail::key_is_empty_condition_impl(key.m_item_tag));
|
||||
}
|
||||
|
||||
inline condition operator !(condition &&rhs)
|
||||
inline condition operator!=(const key &key, const empty_type &)
|
||||
{
|
||||
return condition(new detail::key_is_not_empty_condition_impl(key.m_item_tag));
|
||||
}
|
||||
|
||||
inline condition operator not(condition &&rhs)
|
||||
{
|
||||
return condition(new detail::not_condition_impl(std::move(rhs)));
|
||||
}
|
||||
@@ -741,4 +891,4 @@ namespace literals
|
||||
}
|
||||
} // namespace literals
|
||||
|
||||
} // namespace cif
|
||||
} // namespace cif
|
||||
|
||||
@@ -26,9 +26,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cif++/forward_decl.hpp>
|
||||
|
||||
#include <cif++/category.hpp>
|
||||
#include <cif++/forward_decl.hpp>
|
||||
|
||||
namespace cif
|
||||
{
|
||||
@@ -45,11 +44,10 @@ class datablock : public std::list<category>
|
||||
{
|
||||
}
|
||||
|
||||
datablock(const datablock &) = default;
|
||||
|
||||
datablock(const datablock &);
|
||||
datablock(datablock &&) = default;
|
||||
|
||||
datablock &operator=(const datablock &) = default;
|
||||
datablock &operator=(const datablock &);
|
||||
datablock &operator=(datablock &&) = default;
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
@@ -89,7 +87,7 @@ class datablock : public std::list<category>
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
|
||||
bool operator==(const datablock &rhs) const;
|
||||
|
||||
private:
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
|
||||
#include <list>
|
||||
|
||||
#include <cif++/exports.hpp>
|
||||
#include <cif++/datablock.hpp>
|
||||
#include <cif++/parser.hpp>
|
||||
|
||||
|
||||
@@ -26,6 +26,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cif++/exports.hpp>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
|
||||
@@ -26,6 +26,12 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cif++/exports.hpp>
|
||||
#include <cif++/forward_decl.hpp>
|
||||
#include <cif++/text.hpp>
|
||||
#include <cif++/utilities.hpp>
|
||||
|
||||
#include <cassert>
|
||||
#include <charconv>
|
||||
#include <cstring>
|
||||
#include <iomanip>
|
||||
@@ -35,9 +41,6 @@
|
||||
#include <optional>
|
||||
#include <utility>
|
||||
|
||||
#include <cif++/forward_decl.hpp>
|
||||
#include <cif++/text.hpp>
|
||||
|
||||
/// \file item.hpp
|
||||
/// This file contains the declaration of item but also the item_value and item_handle
|
||||
/// These handle the storage of and access to the data for a single data field.
|
||||
@@ -45,8 +48,6 @@
|
||||
namespace cif
|
||||
{
|
||||
|
||||
extern int VERBOSE;
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
/// \brief item is a transient class that is used to pass data into rows
|
||||
/// but it also takes care of formatting data.
|
||||
@@ -259,8 +260,6 @@ struct item_value
|
||||
}
|
||||
};
|
||||
|
||||
static_assert(sizeof(item_value) == sizeof(void*) + 8, "sizeof(item_value) should be correct");
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// Transient object to access stored data
|
||||
|
||||
@@ -355,7 +354,7 @@ struct item_handle
|
||||
{
|
||||
}
|
||||
|
||||
static const item_handle s_null_item;
|
||||
static CIFPP_EXPORT const item_handle s_null_item;
|
||||
|
||||
friend void swap(item_handle a, item_handle b)
|
||||
{
|
||||
|
||||
@@ -28,6 +28,8 @@
|
||||
|
||||
#include <cif++/row.hpp>
|
||||
|
||||
#include <array>
|
||||
|
||||
namespace cif
|
||||
{
|
||||
|
||||
|
||||
@@ -1,79 +0,0 @@
|
||||
/*-
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*
|
||||
* Copyright (c) 2022 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 <memory>
|
||||
|
||||
namespace cif
|
||||
{
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
template<typename Allocator = std::allocator<void>>
|
||||
class list
|
||||
{
|
||||
public:
|
||||
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
struct list_item
|
||||
{
|
||||
list_item *m_next = nullptr;
|
||||
};
|
||||
|
||||
using list_item_allocator_type = typename std::allocator_traits<Alloc>::template rebind_alloc<list_item>;
|
||||
using list_item_allocator_traits = std::allocator_traits<item_allocator_type>;
|
||||
|
||||
list_item_allocator_traits::pointer get_item()
|
||||
{
|
||||
list_item_allocator_type ia(get_allocator());
|
||||
return list_item_allocator_traits::allocate(ia, 1);
|
||||
}
|
||||
|
||||
template<typename ...Arguments>
|
||||
list_item *create_list_item(uint16_t column_ix, Arguments... args)
|
||||
{
|
||||
auto p = this->get_item();
|
||||
list_item_allocator_type ia(get_allocator());
|
||||
list_item_allocator_traits::construct(ia, p, std::forward<Arguments>(args)...);
|
||||
return p;
|
||||
}
|
||||
|
||||
void delete_list_item(list_item *iv)
|
||||
{
|
||||
list_item_allocator_type ia(get_allocator());
|
||||
list_item_allocator_traits::destroy(ia, iv);
|
||||
list_item_allocator_traits::deallocate(ia, iv, 1);
|
||||
}
|
||||
|
||||
list_item *m_head = nullptr, *m_tail = nullptr;
|
||||
};
|
||||
|
||||
|
||||
} // namespace cif
|
||||
@@ -26,10 +26,10 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <numeric>
|
||||
|
||||
#include <cif++/atom_type.hpp>
|
||||
|
||||
#include <numeric>
|
||||
|
||||
#if __cpp_lib_format
|
||||
#include <format>
|
||||
#endif
|
||||
@@ -50,7 +50,7 @@ class atom
|
||||
private:
|
||||
struct atom_impl : public std::enable_shared_from_this<atom_impl>
|
||||
{
|
||||
atom_impl(datablock &db, std::string_view id)
|
||||
atom_impl(const datablock &db, std::string_view id)
|
||||
: m_db(db)
|
||||
, m_cat(db["atom_site"])
|
||||
, m_id(id)
|
||||
@@ -111,7 +111,7 @@ class atom
|
||||
}
|
||||
|
||||
const datablock &m_db;
|
||||
category &m_cat;
|
||||
const category &m_cat;
|
||||
std::string m_id;
|
||||
point m_location;
|
||||
std::string m_symop = "1_555";
|
||||
@@ -130,7 +130,7 @@ class atom
|
||||
{
|
||||
}
|
||||
|
||||
atom(datablock &db, row_handle &row)
|
||||
atom(const datablock &db, const row_handle &row)
|
||||
: atom(std::make_shared<atom_impl>(db, row["id"].as<std::string>()))
|
||||
{
|
||||
}
|
||||
@@ -321,13 +321,6 @@ class atom
|
||||
|
||||
friend std::ostream &operator<<(std::ostream &os, const atom &atom);
|
||||
|
||||
// /// \brief Synchronize data with underlying cif data
|
||||
// void sync()
|
||||
// {
|
||||
// if (m_impl)
|
||||
// m_impl->prefetch();
|
||||
// }
|
||||
|
||||
private:
|
||||
friend class structure;
|
||||
|
||||
@@ -341,25 +334,6 @@ class atom
|
||||
std::shared_ptr<atom_impl> m_impl;
|
||||
};
|
||||
|
||||
// template <>
|
||||
// inline std::string atom::get_property<std::string>(const std::string_view name) const
|
||||
// {
|
||||
// return get_property(name);
|
||||
// }
|
||||
|
||||
// template <>
|
||||
// inline int atom::get_property<int>(const std::string_view name) const
|
||||
// {
|
||||
// auto v = impl().get_property(name);
|
||||
// return v.empty() ? 0 : stoi(v);
|
||||
// }
|
||||
|
||||
// template <>
|
||||
// inline float atom::get_property<float>(const std::string_view name) const
|
||||
// {
|
||||
// return stof(impl().get_property(name));
|
||||
// }
|
||||
|
||||
inline void swap(atom &a, atom &b)
|
||||
{
|
||||
a.swap(b);
|
||||
@@ -394,7 +368,7 @@ class residue
|
||||
friend class structure;
|
||||
|
||||
// constructor
|
||||
residue(const structure &structure, const std::string &compoundID,
|
||||
residue(structure &structure, const std::string &compoundID,
|
||||
const std::string &asymID, int seqID,
|
||||
const std::string &authAsymID, const std::string &authSeqID,
|
||||
const std::string &pdbInsCode)
|
||||
@@ -408,6 +382,8 @@ class residue
|
||||
{
|
||||
}
|
||||
|
||||
residue(structure &structure, const std::vector<atom> &atoms);
|
||||
|
||||
residue(const residue &rhs) = delete;
|
||||
residue &operator=(const residue &rhs) = delete;
|
||||
|
||||
@@ -430,7 +406,7 @@ class residue
|
||||
const std::string &get_compound_id() const { return m_compound_id; }
|
||||
void set_compound_id(const std::string &id) { m_compound_id = id; }
|
||||
|
||||
const structure *get_structure() const { return m_structure; }
|
||||
structure *get_structure() const { return m_structure; }
|
||||
|
||||
// const compound &compound() const;
|
||||
|
||||
@@ -487,7 +463,7 @@ class residue
|
||||
protected:
|
||||
residue() {}
|
||||
|
||||
const structure *m_structure = nullptr;
|
||||
structure *m_structure = nullptr;
|
||||
std::string m_compound_id, m_asym_id;
|
||||
int m_seq_id = 0;
|
||||
std::string m_auth_asym_id, m_auth_seq_id, m_pdb_ins_code;
|
||||
@@ -571,7 +547,7 @@ class monomer : public residue
|
||||
class polymer : public std::vector<monomer>
|
||||
{
|
||||
public:
|
||||
polymer(const structure &s, const std::string &entityID, const std::string &asymID, const std::string &auth_asym_id);
|
||||
polymer(structure &s, const std::string &entityID, const std::string &asymID, const std::string &auth_asym_id);
|
||||
|
||||
polymer(const polymer &) = delete;
|
||||
polymer &operator=(const polymer &) = delete;
|
||||
@@ -579,7 +555,7 @@ class polymer : public std::vector<monomer>
|
||||
// monomer &getBySeqID(int seqID);
|
||||
// const monomer &getBySeqID(int seqID) const;
|
||||
|
||||
const structure *get_structure() const { return m_structure; }
|
||||
structure *get_structure() const { return m_structure; }
|
||||
|
||||
std::string get_asym_id() const { return m_asym_id; }
|
||||
std::string get_auth_asym_id() const { return m_auth_asym_id; } // The PDB chain ID, actually
|
||||
@@ -588,7 +564,7 @@ class polymer : public std::vector<monomer>
|
||||
// int Distance(const monomer &a, const monomer &b) const;
|
||||
|
||||
private:
|
||||
const structure *m_structure;
|
||||
structure *m_structure;
|
||||
std::string m_entity_id;
|
||||
std::string m_asym_id;
|
||||
std::string m_auth_asym_id;
|
||||
@@ -602,7 +578,7 @@ class branch;
|
||||
class sugar : public residue
|
||||
{
|
||||
public:
|
||||
sugar(const branch &branch, const std::string &compoundID,
|
||||
sugar(branch &branch, const std::string &compoundID,
|
||||
const std::string &asymID, int authSeqID);
|
||||
|
||||
sugar(sugar &&rhs);
|
||||
@@ -629,27 +605,44 @@ class sugar : public residue
|
||||
return result;
|
||||
}
|
||||
|
||||
cif::mm::atom add_atom(row_initializer atom_info);
|
||||
|
||||
private:
|
||||
const branch *m_branch;
|
||||
branch *m_branch;
|
||||
atom m_link;
|
||||
};
|
||||
|
||||
class branch : public std::vector<sugar>
|
||||
{
|
||||
public:
|
||||
branch(structure &structure, const std::string &asymID);
|
||||
branch(structure &structure, const std::string &asym_id, const std::string &entity_id);
|
||||
|
||||
branch(const branch &) = delete;
|
||||
branch &operator=(const branch &) = delete;
|
||||
|
||||
branch(branch &&) = default;
|
||||
branch &operator=(branch &&) = default;
|
||||
|
||||
void link_atoms();
|
||||
|
||||
std::string name() const;
|
||||
float weight() const;
|
||||
std::string get_asym_id() const { return m_asym_id; }
|
||||
std::string get_entity_id() const { return m_entity_id; }
|
||||
|
||||
structure &get_structure() { return *m_structure; }
|
||||
const structure &get_structure() const { return *m_structure; }
|
||||
structure &get_structure() const { return *m_structure; }
|
||||
|
||||
sugar &getSugarByNum(int nr);
|
||||
const sugar &getSugarByNum(int nr) const;
|
||||
sugar &get_sugar_by_num(int nr);
|
||||
|
||||
const sugar &get_sugar_by_num(int nr) const
|
||||
{
|
||||
return const_cast<branch *>(this)->get_sugar_by_num(nr);
|
||||
}
|
||||
|
||||
sugar &construct_sugar(const std::string &compound_id);
|
||||
sugar &construct_sugar(const std::string &compound_id, const std::string &atom_id,
|
||||
int linked_sugar_nr, const std::string &linked_atom_id);
|
||||
|
||||
private:
|
||||
friend sugar;
|
||||
@@ -657,7 +650,7 @@ class branch : public std::vector<sugar>
|
||||
std::string name(const sugar &s) const;
|
||||
|
||||
structure *m_structure;
|
||||
std::string m_asym_id;
|
||||
std::string m_asym_id, m_entity_id;
|
||||
};
|
||||
|
||||
// // --------------------------------------------------------------------
|
||||
@@ -763,6 +756,9 @@ class structure
|
||||
/// \brief Return the atom closest to point \a p with atom type \a type in a residue of type \a res_type
|
||||
atom get_atom_by_position_and_type(point p, std::string_view type, std::string_view res_type) const;
|
||||
|
||||
/// \brief Create a non-poly residue based on atoms already present in this structure.
|
||||
residue &create_residue(const std::vector<atom> &atoms);
|
||||
|
||||
/// \brief Get a non-poly residue for an asym with id \a asymID
|
||||
residue &get_residue(const std::string &asymID)
|
||||
{
|
||||
@@ -820,10 +816,7 @@ class structure
|
||||
///
|
||||
/// \param asym_id The asym ID
|
||||
/// \param seq_id The sequence ID
|
||||
void remove_residue(const std::string &asym_id, int seq_id, const std::string &auth_seq_id)
|
||||
{
|
||||
remove_residue(get_residue(asym_id, seq_id, auth_seq_id));
|
||||
}
|
||||
void remove_residue(const std::string &asym_id, int seq_id, const std::string &auth_seq_id);
|
||||
|
||||
/// \brief Create a new non-polymer entity, returns new ID
|
||||
/// \param mon_id The mon_id for the new nonpoly, must be an existing and known compound from CCD
|
||||
@@ -846,6 +839,9 @@ class structure
|
||||
/// \return The newly create asym ID
|
||||
std::string create_non_poly(const std::string &entity_id, std::vector<row_initializer> atoms);
|
||||
|
||||
/// \brief Create a new and empty (sugar) branch
|
||||
branch &create_branch();
|
||||
|
||||
/// \brief Create a new (sugar) branch with one first NAG containing atoms constructed from \a atoms
|
||||
branch &create_branch(std::vector<row_initializer> atoms);
|
||||
|
||||
@@ -893,6 +889,18 @@ class structure
|
||||
|
||||
void validate_atoms() const;
|
||||
|
||||
// TODO: make this protected?
|
||||
|
||||
void load_atoms_for_model(StructureOpenOptions options);
|
||||
|
||||
template <typename... Args>
|
||||
atom &emplace_atom(Args&... args)
|
||||
{
|
||||
return emplace_atom(atom{ std::forward<Args>(args)... });
|
||||
}
|
||||
|
||||
atom &emplace_atom(atom &&atom);
|
||||
|
||||
private:
|
||||
friend polymer;
|
||||
friend residue;
|
||||
@@ -903,16 +911,6 @@ class structure
|
||||
|
||||
void load_data();
|
||||
|
||||
void load_atoms_for_model(StructureOpenOptions options);
|
||||
|
||||
template <typename... Args>
|
||||
atom &emplace_atom(Args... args)
|
||||
{
|
||||
return emplace_atom(atom{ std::forward<Args>(args)... });
|
||||
}
|
||||
|
||||
atom &emplace_atom(atom &&atom);
|
||||
|
||||
void remove_atom(atom &a, bool removeFromResidue);
|
||||
void remove_sugar(sugar &sugar);
|
||||
|
||||
@@ -925,4 +923,11 @@ class structure
|
||||
std::vector<residue> m_non_polymers;
|
||||
};
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
/// \brief Reconstruct all missing categories for an assumed PDBx file.
|
||||
/// Some people believe that simply dumping some atom records is enough.
|
||||
/// \param db The cif::datablock that hopefully contains some valid data
|
||||
void reconstruct_pdbx(datablock &db);
|
||||
|
||||
} // namespace cif::mm
|
||||
|
||||
@@ -26,10 +26,11 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <map>
|
||||
|
||||
#include <cif++/row.hpp>
|
||||
|
||||
#include <map>
|
||||
#include <regex>
|
||||
|
||||
namespace cif
|
||||
{
|
||||
|
||||
@@ -93,23 +94,23 @@ class sac_parser
|
||||
|
||||
static bool is_unquoted_string(std::string_view text)
|
||||
{
|
||||
auto s = text.begin();
|
||||
bool result = text.empty() or is_ordinary(text.front());
|
||||
|
||||
bool result = is_ordinary(*s++);
|
||||
while (result and s != text.end())
|
||||
{
|
||||
result = is_non_blank(*s);
|
||||
++s;
|
||||
}
|
||||
|
||||
// but be careful it does not contain e.g. stop_
|
||||
if (result)
|
||||
{
|
||||
static const std::regex reservedRx(R"((^(?:data|save)|.*(?:loop|stop|global))_.+)", std::regex_constants::icase);
|
||||
result = not std::regex_match(text.begin(), text.end(), reservedRx);
|
||||
for (auto ch : text)
|
||||
{
|
||||
if (is_non_blank(ch))
|
||||
continue;
|
||||
result = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
static const std::regex kReservedRx(R"(loop_|stop_|global_|data_\S+|save_\S+)", std::regex_constants::icase);
|
||||
|
||||
// but be careful it does not contain e.g. stop_
|
||||
return result and not std::regex_match(text.begin(), text.end(), kReservedRx);
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
@@ -26,19 +26,15 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cif++.hpp>
|
||||
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
#include <vector>
|
||||
|
||||
#include <cif++.hpp>
|
||||
|
||||
namespace cif
|
||||
{
|
||||
|
||||
extern const int
|
||||
kResidueNrWildcard,
|
||||
kNoSeqNum;
|
||||
|
||||
struct tls_selection;
|
||||
struct tls_residue;
|
||||
|
||||
|
||||
@@ -26,6 +26,9 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cif++/exports.hpp>
|
||||
|
||||
#include <array>
|
||||
#include <cmath>
|
||||
#include <complex>
|
||||
#include <functional>
|
||||
@@ -54,7 +57,7 @@ class quaternion_type
|
||||
public:
|
||||
using value_type = T;
|
||||
|
||||
constexpr explicit quaternion_type(value_type const &value_a = value_type(), value_type const &value_b = value_type(), value_type const &value_c = value_type(), value_type const &value_d = value_type())
|
||||
constexpr explicit quaternion_type(value_type const &value_a = {}, value_type const &value_b = {}, value_type const &value_c = {}, value_type const &value_d = {})
|
||||
: a(value_a)
|
||||
, b(value_b)
|
||||
, c(value_c)
|
||||
@@ -305,6 +308,21 @@ class quaternion_type
|
||||
constexpr value_type get_c() const { return c; }
|
||||
constexpr value_type get_d() const { return d; }
|
||||
|
||||
constexpr bool operator==(const quaternion_type &rhs) const
|
||||
{
|
||||
return a == rhs.a and b == rhs.b and c == rhs.c and d == rhs.d;
|
||||
}
|
||||
|
||||
constexpr bool operator!=(const quaternion_type &rhs) const
|
||||
{
|
||||
return a != rhs.a or b != rhs.b or c != rhs.c or d != rhs.d;
|
||||
}
|
||||
|
||||
constexpr operator bool() const
|
||||
{
|
||||
return operator!=({});
|
||||
}
|
||||
|
||||
private:
|
||||
value_type a, b, c, d;
|
||||
};
|
||||
@@ -483,6 +501,13 @@ struct point_type
|
||||
m_z = p.get_d();
|
||||
}
|
||||
|
||||
constexpr void rotate(const quaternion &q, point_type pivot)
|
||||
{
|
||||
operator-=(pivot);
|
||||
rotate(q);
|
||||
operator+=(pivot);
|
||||
}
|
||||
|
||||
#if HAVE_LIBCLIPPER
|
||||
operator clipper::Coord_orth() const
|
||||
{
|
||||
@@ -665,6 +690,12 @@ point nudge(point p, float offset);
|
||||
quaternion construct_from_angle_axis(float angle, point axis);
|
||||
std::tuple<double, point> quaternion_to_angle_axis(quaternion q);
|
||||
|
||||
/// @brief Given four points and an angle, return the quaternion required to rotate
|
||||
/// point p4 along the p2-p3 axis and around point p3 to obtain the required within
|
||||
/// an accuracy of esd
|
||||
quaternion construct_for_dihedral_angle(point p1, point p2, point p3, point p4,
|
||||
float angle, float esd);
|
||||
|
||||
point centroid(const std::vector<point> &Points);
|
||||
point center_points(std::vector<point> &Points);
|
||||
|
||||
|
||||
@@ -28,6 +28,8 @@
|
||||
|
||||
#include <cif++/item.hpp>
|
||||
|
||||
#include <array>
|
||||
|
||||
namespace cif
|
||||
{
|
||||
|
||||
|
||||
@@ -26,6 +26,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cif++/exports.hpp>
|
||||
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
@@ -50,8 +52,8 @@ struct space_group
|
||||
int nr;
|
||||
};
|
||||
|
||||
extern const space_group kSpaceGroups[];
|
||||
extern const std::size_t kNrOfSpaceGroups;
|
||||
extern CIFPP_EXPORT const space_group kSpaceGroups[];
|
||||
extern CIFPP_EXPORT const std::size_t kNrOfSpaceGroups;
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
@@ -139,8 +141,8 @@ struct symop_datablock
|
||||
|
||||
static_assert(sizeof(symop_datablock) == sizeof(uint64_t), "Size of symop_data is wrong");
|
||||
|
||||
extern const symop_datablock kSymopNrTable[];
|
||||
extern const std::size_t kSymopNrTableSize;
|
||||
extern CIFPP_EXPORT const symop_datablock kSymopNrTable[];
|
||||
extern CIFPP_EXPORT const std::size_t kSymopNrTableSize;
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
|
||||
@@ -26,6 +26,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cif++/exports.hpp>
|
||||
|
||||
#include <charconv>
|
||||
#include <cmath>
|
||||
#include <limits>
|
||||
@@ -34,70 +36,11 @@
|
||||
#include <tuple>
|
||||
#include <vector>
|
||||
|
||||
|
||||
#if __has_include(<experimental/type_traits>)
|
||||
#include <experimental/type_traits>
|
||||
#else
|
||||
#include <type_traits>
|
||||
#endif
|
||||
|
||||
#if (not defined(__cpp_lib_experimental_detect) or (__cpp_lib_experimental_detect < 201505)) and (not defined(_LIBCPP_VERSION) or _LIBCPP_VERSION < 5000)
|
||||
// This code is copied from:
|
||||
// https://ld2015.scusa.lsu.edu/cppreference/en/cpp/experimental/is_detected.html
|
||||
|
||||
namespace std
|
||||
{
|
||||
template< class... >
|
||||
using void_t = void;
|
||||
|
||||
namespace experimental
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
template <class Default, class AlwaysVoid,
|
||||
template<class...> class Op, class... Args>
|
||||
struct detector
|
||||
{
|
||||
using value_t = false_type;
|
||||
using type = Default;
|
||||
};
|
||||
|
||||
template <class Default, template<class...> class Op, class... Args>
|
||||
struct detector<Default, void_t<Op<Args...>>, Op, Args...> {
|
||||
// Note that std::void_t is a c++17 feature
|
||||
using value_t = true_type;
|
||||
using type = Op<Args...>;
|
||||
};
|
||||
} // namespace detail
|
||||
|
||||
struct nonesuch
|
||||
{
|
||||
nonesuch() = delete;
|
||||
~nonesuch() = delete;
|
||||
nonesuch(nonesuch const&) = delete;
|
||||
void operator=(nonesuch const&) = delete;
|
||||
};
|
||||
|
||||
template <template<class...> class Op, class... Args>
|
||||
using is_detected = typename detail::detector<nonesuch, void, Op, Args...>::value_t;
|
||||
|
||||
template <template<class...> class Op, class... Args>
|
||||
constexpr inline bool is_detected_v = is_detected<Op,Args...>::value;
|
||||
|
||||
template <template<class...> class Op, class... Args>
|
||||
using detected_t = typename detail::detector<nonesuch, void, Op, Args...>::type;
|
||||
|
||||
template <class Default, template<class...> class Op, class... Args>
|
||||
using detected_or = detail::detector<Default, void, Op, Args...>;
|
||||
|
||||
template <class Expected, template <class...> class Op, class... Args>
|
||||
using is_detected_exact = std::is_same<Expected, detected_t<Op, Args...>>;
|
||||
|
||||
template <class Expected, template<class...> class Op, class... Args>
|
||||
constexpr inline bool is_detected_exact_v = is_detected_exact<Expected, Op, Args...>::value;
|
||||
}
|
||||
}
|
||||
|
||||
// sub optimal, but replicating the same code is worse
|
||||
#include <zeep/type-traits.hpp>
|
||||
#endif
|
||||
|
||||
namespace cif
|
||||
@@ -249,7 +192,7 @@ typedef std::set<std::string, iless> iset;
|
||||
// --------------------------------------------------------------------
|
||||
// This really makes a difference, having our own tolower routines
|
||||
|
||||
extern const uint8_t kCharToLowerMap[256];
|
||||
extern CIFPP_EXPORT const uint8_t kCharToLowerMap[256];
|
||||
|
||||
inline char tolower(int ch)
|
||||
{
|
||||
@@ -448,8 +391,8 @@ std::to_chars_result to_chars(char *first, char *last, FloatType &value, chars_f
|
||||
template <typename FloatType, std::enable_if_t<std::is_floating_point_v<FloatType>, int> = 0>
|
||||
std::to_chars_result to_chars(char *first, char *last, FloatType &value, chars_format fmt, int precision)
|
||||
{
|
||||
int size = last - first;
|
||||
int r;
|
||||
int size = static_cast<int>(last - first);
|
||||
int r = 0;
|
||||
|
||||
switch (fmt)
|
||||
{
|
||||
|
||||
@@ -26,6 +26,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cif++/exports.hpp>
|
||||
|
||||
#include <filesystem>
|
||||
|
||||
#ifndef STDOUT_FILENO
|
||||
@@ -50,7 +52,7 @@
|
||||
namespace cif
|
||||
{
|
||||
|
||||
extern int VERBOSE;
|
||||
extern CIFPP_EXPORT int VERBOSE;
|
||||
|
||||
// the git 'build' number
|
||||
std::string get_version_nr();
|
||||
|
||||
@@ -26,13 +26,13 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cif++/text.hpp>
|
||||
|
||||
#include <filesystem>
|
||||
#include <list>
|
||||
#include <mutex>
|
||||
#include <utility>
|
||||
|
||||
#include <cif++/text.hpp>
|
||||
|
||||
namespace cif
|
||||
{
|
||||
|
||||
|
||||
@@ -182,24 +182,24 @@ const struct ionic_radii
|
||||
{ F, { kNA, kNA, 119, kNA, kNA, kNA, kNA, kNA, kNA, 22, kNA } }, // Fluorine
|
||||
{ Na, { kNA, kNA, kNA, 116, kNA, kNA, kNA, kNA, kNA, kNA, kNA } }, // Sodium
|
||||
{ Mg, { kNA, kNA, kNA, kNA, 86, kNA, kNA, kNA, kNA, kNA, kNA } }, // Magnesium
|
||||
{ Al, { kNA, kNA, kNA, kNA, kNA, 67.5, kNA, kNA, kNA, kNA, kNA } }, // Aluminium
|
||||
{ Al, { kNA, kNA, kNA, kNA, kNA, 67.5f, kNA, kNA, kNA, kNA, kNA } }, // Aluminium
|
||||
{ Si, { kNA, kNA, kNA, kNA, kNA, kNA, 54, kNA, kNA, kNA, kNA } }, // Silicon
|
||||
{ P, { kNA, kNA, kNA, kNA, kNA, 58, kNA, 52, kNA, kNA, kNA } }, // Phosphorus
|
||||
{ S, { kNA, 170, kNA, kNA, kNA, kNA, 51, kNA, 43, kNA, kNA } }, // Sulfur
|
||||
{ Cl, { kNA, kNA, 181, kNA, kNA, kNA, kNA, 26, kNA, 41, kNA } }, // Chlorine
|
||||
{ K, { kNA, kNA, kNA, 152, kNA, kNA, kNA, kNA, kNA, kNA, kNA } }, // Potassium
|
||||
{ Ca, { kNA, kNA, kNA, kNA, 114, kNA, kNA, kNA, kNA, kNA, kNA } }, // Calcium
|
||||
{ Sc, { kNA, kNA, kNA, kNA, kNA, 88.5, kNA, kNA, kNA, kNA, kNA } }, // Scandium
|
||||
{ Ti, { kNA, kNA, kNA, kNA, 100, 81, 74.5, kNA, kNA, kNA, kNA } }, // Titanium
|
||||
{ Sc, { kNA, kNA, kNA, kNA, kNA, 88.5f, kNA, kNA, kNA, kNA, kNA } }, // Scandium
|
||||
{ Ti, { kNA, kNA, kNA, kNA, 100, 81, 74.5f, kNA, kNA, kNA, kNA } }, // Titanium
|
||||
{ V, { kNA, kNA, kNA, kNA, 93, 78, 72, 68, kNA, kNA, kNA } }, // Vanadium
|
||||
{ Cr, { kNA, kNA, kNA, kNA, 87, 75.5, 69, 63, 58, kNA, kNA } }, // Chromium ls
|
||||
{ Cr, { kNA, kNA, kNA, kNA, 87, 75.5f, 69, 63, 58, kNA, kNA } }, // Chromium ls
|
||||
// { Cr,{ kNA, kNA, kNA, kNA, 94, kNA, kNA, kNA, kNA, kNA, kNA } }, // Chromium hs
|
||||
{ Mn, { kNA, kNA, kNA, kNA, 81, 72, 67, 47, 39.5, 60, kNA } }, // Manganese ls
|
||||
// { Mn,{ kNA, kNA, kNA, kNA, 97, 78.5, kNA, kNA, kNA, kNA, kNA } }, // Manganese hs
|
||||
{ Fe, { kNA, kNA, kNA, kNA, 75, 69, 72.5, kNA, 39, kNA, kNA } }, // Iron ls
|
||||
// { Fe,{ kNA, kNA, kNA, kNA, 92, 78.5, kNA, kNA, kNA, kNA, kNA } }, // Iron hs
|
||||
{ Co, { kNA, kNA, kNA, kNA, 79, 68.5, kNA, kNA, kNA, kNA, kNA } }, // Cobalt ls
|
||||
// { Co,{ kNA, kNA, kNA, kNA, 88.5, 75, 67, kNA, kNA, kNA, kNA } }, // Cobalt hs
|
||||
{ Mn, { kNA, kNA, kNA, kNA, 81, 72, 67, 47, 39.5f, 60, kNA } }, // Manganese ls
|
||||
// { Mn,{ kNA, kNA, kNA, kNA, 97, 78.5f, kNA, kNA, kNA, kNA, kNA } }, // Manganese hs
|
||||
{ Fe, { kNA, kNA, kNA, kNA, 75, 69, 72.5f, kNA, 39, kNA, kNA } }, // Iron ls
|
||||
// { Fe,{ kNA, kNA, kNA, kNA, 92, 78.5f, kNA, kNA, kNA, kNA, kNA } }, // Iron hs
|
||||
{ Co, { kNA, kNA, kNA, kNA, 79, 68.5f, kNA, kNA, kNA, kNA, kNA } }, // Cobalt ls
|
||||
// { Co,{ kNA, kNA, kNA, kNA, 88.5f, 75, 67, kNA, kNA, kNA, kNA } }, // Cobalt hs
|
||||
{ Ni, { kNA, kNA, kNA, kNA, 83, 70, 62, kNA, kNA, kNA, kNA } }, // Nickel ls
|
||||
// { Ni,{ kNA, kNA, kNA, kNA, kNA, 74, kNA, kNA, kNA, kNA, kNA } }, // Nickel hs
|
||||
{ Cu, { kNA, kNA, kNA, 91, 87, 68, kNA, kNA, kNA, kNA, kNA } }, // Copper
|
||||
@@ -215,10 +215,10 @@ const struct ionic_radii
|
||||
{ Zr, { kNA, kNA, kNA, kNA, kNA, kNA, 86, kNA, kNA, kNA, kNA } }, // Zirconium
|
||||
{ Nb, { kNA, kNA, kNA, kNA, kNA, 86, 82, 78, kNA, kNA, kNA } }, // Niobium
|
||||
{ Mo, { kNA, kNA, kNA, kNA, kNA, 83, 79, 75, 73, kNA, kNA } }, // Molybdenum
|
||||
{ Tc, { kNA, kNA, kNA, kNA, kNA, kNA, 78.5, 74, kNA, 70, kNA } }, // Technetium
|
||||
{ Ru, { kNA, kNA, kNA, kNA, kNA, 82, 76, 70.5, kNA, 52, 150 } }, // Ruthenium
|
||||
{ Rh, { kNA, kNA, kNA, kNA, kNA, 80.5, 74, 69, kNA, kNA, kNA } }, // Rhodium
|
||||
{ Pd, { kNA, kNA, kNA, 73, 100, 90, 75.5, kNA, kNA, kNA, kNA } }, // Palladium
|
||||
{ Tc, { kNA, kNA, kNA, kNA, kNA, kNA, 78.5f, 74, kNA, 70, kNA } }, // Technetium
|
||||
{ Ru, { kNA, kNA, kNA, kNA, kNA, 82, 76, 70.5f, kNA, 52, 150 } }, // Ruthenium
|
||||
{ Rh, { kNA, kNA, kNA, kNA, kNA, 80.5f, 74, 69, kNA, kNA, kNA } }, // Rhodium
|
||||
{ Pd, { kNA, kNA, kNA, 73, 100, 90, 75.5f, kNA, kNA, kNA, kNA } }, // Palladium
|
||||
{ Ag, { kNA, kNA, kNA, 129, 108, 89, kNA, kNA, kNA, kNA, kNA } }, // Silver
|
||||
{ Cd, { kNA, kNA, kNA, kNA, 109, kNA, kNA, kNA, kNA, kNA, kNA } }, // Cadmium
|
||||
{ In, { kNA, kNA, kNA, kNA, kNA, 94, kNA, kNA, kNA, kNA, kNA } }, // Indium
|
||||
@@ -229,32 +229,32 @@ const struct ionic_radii
|
||||
{ Xe, { kNA, kNA, kNA, kNA, kNA, kNA, kNA, kNA, kNA, kNA, 62 } }, // Xenon
|
||||
{ Cs, { kNA, kNA, kNA, 167, kNA, kNA, kNA, kNA, kNA, kNA, kNA } }, // Caesium
|
||||
{ Ba, { kNA, kNA, kNA, kNA, 149, kNA, kNA, kNA, kNA, kNA, kNA } }, // Barium
|
||||
{ La, { kNA, kNA, kNA, kNA, kNA, 117.2, kNA, kNA, kNA, kNA, kNA } }, // Lanthanum
|
||||
{ La, { kNA, kNA, kNA, kNA, kNA, 117.2f, kNA, kNA, kNA, kNA, kNA } }, // Lanthanum
|
||||
{ Ce, { kNA, kNA, kNA, kNA, kNA, 115, 101, kNA, kNA, kNA, kNA } }, // Cerium
|
||||
{ Pr, { kNA, kNA, kNA, kNA, kNA, 113, 99, kNA, kNA, kNA, kNA } }, // Praseodymium
|
||||
{ Nd, { kNA, kNA, kNA, kNA, 143, 112.3, kNA, kNA, kNA, kNA, kNA } }, // Neodymium
|
||||
{ Nd, { kNA, kNA, kNA, kNA, 143, 112.3f, kNA, kNA, kNA, kNA, kNA } }, // Neodymium
|
||||
{ Pm, { kNA, kNA, kNA, kNA, kNA, 111, kNA, kNA, kNA, kNA, kNA } }, // Promethium
|
||||
{ Sm, { kNA, kNA, kNA, kNA, 136, 109.8, kNA, kNA, kNA, kNA, kNA } }, // Samarium
|
||||
{ Eu, { kNA, kNA, kNA, kNA, 131, 108.7, kNA, kNA, kNA, kNA, kNA } }, // Europium
|
||||
{ Gd, { kNA, kNA, kNA, kNA, kNA, 107.8, kNA, kNA, kNA, kNA, kNA } }, // Gadolinium
|
||||
{ Tb, { kNA, kNA, kNA, kNA, kNA, 106.3, 90, kNA, kNA, kNA, kNA } }, // Terbium
|
||||
{ Dy, { kNA, kNA, kNA, kNA, 121, 105.2, kNA, kNA, kNA, kNA, kNA } }, // Dysprosium
|
||||
{ Ho, { kNA, kNA, kNA, kNA, kNA, 104.1, kNA, kNA, kNA, kNA, kNA } }, // Holmium
|
||||
{ Sm, { kNA, kNA, kNA, kNA, 136, 109.8f, kNA, kNA, kNA, kNA, kNA } }, // Samarium
|
||||
{ Eu, { kNA, kNA, kNA, kNA, 131, 108.7f, kNA, kNA, kNA, kNA, kNA } }, // Europium
|
||||
{ Gd, { kNA, kNA, kNA, kNA, kNA, 107.8f, kNA, kNA, kNA, kNA, kNA } }, // Gadolinium
|
||||
{ Tb, { kNA, kNA, kNA, kNA, kNA, 106.3f, 90, kNA, kNA, kNA, kNA } }, // Terbium
|
||||
{ Dy, { kNA, kNA, kNA, kNA, 121, 105.2f, kNA, kNA, kNA, kNA, kNA } }, // Dysprosium
|
||||
{ Ho, { kNA, kNA, kNA, kNA, kNA, 104.1f, kNA, kNA, kNA, kNA, kNA } }, // Holmium
|
||||
{ Er, { kNA, kNA, kNA, kNA, kNA, 103, kNA, kNA, kNA, kNA, kNA } }, // Erbium
|
||||
{ Tm, { kNA, kNA, kNA, kNA, 117, 102, kNA, kNA, kNA, kNA, kNA } }, // Thulium
|
||||
{ Yb, { kNA, kNA, kNA, kNA, 116, 100.8, kNA, kNA, kNA, kNA, kNA } }, // Ytterbium
|
||||
{ Lu, { kNA, kNA, kNA, kNA, kNA, 100.1, kNA, kNA, kNA, kNA, kNA } }, // Lutetium
|
||||
{ Yb, { kNA, kNA, kNA, kNA, 116, 100.8f, kNA, kNA, kNA, kNA, kNA } }, // Ytterbium
|
||||
{ Lu, { kNA, kNA, kNA, kNA, kNA, 100.1f, kNA, kNA, kNA, kNA, kNA } }, // Lutetium
|
||||
{ Hf, { kNA, kNA, kNA, kNA, kNA, kNA, 85, kNA, kNA, kNA, kNA } }, // Hafnium
|
||||
{ Ta, { kNA, kNA, kNA, kNA, kNA, 86, 82, 78, kNA, kNA, kNA } }, // Tantalum
|
||||
{ W, { kNA, kNA, kNA, kNA, kNA, kNA, 80, 76, 74, kNA, kNA } }, // Tungsten
|
||||
{ Re, { kNA, kNA, kNA, kNA, kNA, kNA, 77, 72, 69, 67, kNA } }, // Rhenium
|
||||
{ Os, { kNA, kNA, kNA, kNA, kNA, kNA, 77, 71.5, 68.5, 66.5, 53 } }, // Osmium
|
||||
{ Ir, { kNA, kNA, kNA, kNA, kNA, 82, 76.5, 71, kNA, kNA, kNA } }, // Iridium
|
||||
{ Pt, { kNA, kNA, kNA, kNA, 94, kNA, 76.5, 71, kNA, kNA, kNA } }, // Platinum
|
||||
{ Os, { kNA, kNA, kNA, kNA, kNA, kNA, 77, 71.5f, 68.5f, 66.5f, 53 } }, // Osmium
|
||||
{ Ir, { kNA, kNA, kNA, kNA, kNA, 82, 76.5f, 71, kNA, kNA, kNA } }, // Iridium
|
||||
{ Pt, { kNA, kNA, kNA, kNA, 94, kNA, 76.5f, 71, kNA, kNA, kNA } }, // Platinum
|
||||
{ Au, { kNA, kNA, kNA, 151, kNA, 99, kNA, 71, kNA, kNA, kNA } }, // Gold
|
||||
{ Hg, { kNA, kNA, kNA, 133, 116, kNA, kNA, kNA, kNA, kNA, kNA } }, // Mercury
|
||||
{ Tl, { kNA, kNA, kNA, 164, kNA, 102.5, kNA, kNA, kNA, kNA, kNA } }, // Thallium
|
||||
{ Pb, { kNA, kNA, kNA, kNA, 133, kNA, 91.5, kNA, kNA, kNA, kNA } }, // Lead
|
||||
{ Tl, { kNA, kNA, kNA, 164, kNA, 102.5f, kNA, kNA, kNA, kNA, kNA } }, // Thallium
|
||||
{ Pb, { kNA, kNA, kNA, kNA, 133, kNA, 91.5f, kNA, kNA, kNA, kNA } }, // Lead
|
||||
{ Bi, { kNA, kNA, kNA, kNA, kNA, 117, kNA, 90, kNA, kNA, kNA } }, // Bismuth
|
||||
{ Po, { kNA, kNA, kNA, kNA, kNA, kNA, 108, kNA, 81, kNA, kNA } }, // Polonium
|
||||
{ At, { kNA, kNA, kNA, kNA, kNA, kNA, kNA, kNA, kNA, 76, kNA } }, // Astatine
|
||||
@@ -263,16 +263,16 @@ const struct ionic_radii
|
||||
{ Ac, { kNA, kNA, kNA, kNA, kNA, 126, kNA, kNA, kNA, kNA, kNA } }, // Actinium
|
||||
{ Th, { kNA, kNA, kNA, kNA, kNA, kNA, 108, kNA, kNA, kNA, kNA } }, // Thorium
|
||||
{ Pa, { kNA, kNA, kNA, kNA, kNA, 116, 104, 92, kNA, kNA, kNA } }, // Protactinium
|
||||
{ U, { kNA, kNA, kNA, kNA, kNA, 116.5, 103, 90, 87, kNA, kNA } }, // Uranium
|
||||
{ U, { kNA, kNA, kNA, kNA, kNA, 116.5f, 103, 90, 87, kNA, kNA } }, // Uranium
|
||||
{ Np, { kNA, kNA, kNA, kNA, 124, 115, 101, 89, 86, 85, kNA } }, // Neptunium
|
||||
{ Pu, { kNA, kNA, kNA, kNA, kNA, 114, 100, 88, 85, kNA, kNA } }, // Plutonium
|
||||
{ Am, { kNA, kNA, kNA, kNA, 140, 111.5, 99, kNA, kNA, kNA, kNA } }, // Americium
|
||||
{ Am, { kNA, kNA, kNA, kNA, 140, 111.5f, 99, kNA, kNA, kNA, kNA } }, // Americium
|
||||
{ Cm, { kNA, kNA, kNA, kNA, kNA, 111, 99, kNA, kNA, kNA, kNA } }, // Curium
|
||||
{ Bk, { kNA, kNA, kNA, kNA, kNA, 110, 97, kNA, kNA, kNA, kNA } }, // Berkelium
|
||||
{ Cf, { kNA, kNA, kNA, kNA, kNA, 109, 96.1, kNA, kNA, kNA, kNA } }, // Californium
|
||||
{ Es, { kNA, kNA, kNA, kNA, kNA, 92.8, kNA, kNA, kNA, kNA, kNA } }, // Einsteinium
|
||||
{ Cf, { kNA, kNA, kNA, kNA, kNA, 109, 96.1f, kNA, kNA, kNA, kNA } }, // Californium
|
||||
{ Es, { kNA, kNA, kNA, kNA, kNA, 92.8f, kNA, kNA, kNA, kNA, kNA } }, // Einsteinium
|
||||
}, kEffectiveIonicRadii[] = {
|
||||
{ H, { kNA, kNA, 139.9, -18, kNA, kNA, kNA, kNA, kNA, kNA, kNA } }, // Hydrogen
|
||||
{ H, { kNA, kNA, 139.9f, -18, kNA, kNA, kNA, kNA, kNA, kNA, kNA } }, // Hydrogen
|
||||
{ Li, { kNA, kNA, kNA, 76, kNA, kNA, kNA, kNA, kNA, kNA, kNA } }, // Lithium
|
||||
{ Be, { kNA, kNA, kNA, kNA, 45, kNA, kNA, kNA, kNA, kNA, kNA } }, // Beryllium
|
||||
{ B, { kNA, kNA, kNA, kNA, kNA, 27, kNA, kNA, kNA, kNA, kNA } }, // Boron
|
||||
@@ -282,24 +282,24 @@ const struct ionic_radii
|
||||
{ F, { kNA, kNA, 133, kNA, kNA, kNA, kNA, kNA, kNA, 8, kNA } }, // Fluorine
|
||||
{ Na, { kNA, kNA, kNA, 102, kNA, kNA, kNA, kNA, kNA, kNA, kNA } }, // Sodium
|
||||
{ Mg, { kNA, kNA, kNA, kNA, 72, kNA, kNA, kNA, kNA, kNA, kNA } }, // Magnesium
|
||||
{ Al, { kNA, kNA, kNA, kNA, kNA, 53.5, kNA, kNA, kNA, kNA, kNA } }, // Aluminium
|
||||
{ Al, { kNA, kNA, kNA, kNA, kNA, 53.5f, kNA, kNA, kNA, kNA, kNA } }, // Aluminium
|
||||
{ Si, { kNA, kNA, kNA, kNA, kNA, kNA, 40, kNA, kNA, kNA, kNA } }, // Silicon
|
||||
{ P, { 212, kNA, kNA, kNA, kNA, 44, kNA, 38, kNA, kNA, kNA } }, // Phosphorus
|
||||
{ S, { kNA, 184, kNA, kNA, kNA, kNA, 37, kNA, 29, kNA, kNA } }, // Sulfur
|
||||
{ Cl, { kNA, kNA, 181, kNA, kNA, kNA, kNA, 12, kNA, 27, kNA } }, // Chlorine
|
||||
{ K, { kNA, kNA, kNA, 138, kNA, kNA, kNA, kNA, kNA, kNA, kNA } }, // Potassium
|
||||
{ Ca, { kNA, kNA, kNA, kNA, 100, kNA, kNA, kNA, kNA, kNA, kNA } }, // Calcium
|
||||
{ Sc, { kNA, kNA, kNA, kNA, kNA, 74.5, kNA, kNA, kNA, kNA, kNA } }, // Scandium
|
||||
{ Ti, { kNA, kNA, kNA, kNA, 86, 67, 60.5, kNA, kNA, kNA, kNA } }, // Titanium
|
||||
{ Sc, { kNA, kNA, kNA, kNA, kNA, 74.5f, kNA, kNA, kNA, kNA, kNA } }, // Scandium
|
||||
{ Ti, { kNA, kNA, kNA, kNA, 86, 67, 60.5f, kNA, kNA, kNA, kNA } }, // Titanium
|
||||
{ V, { kNA, kNA, kNA, kNA, 79, 64, 58, 54, kNA, kNA, kNA } }, // Vanadium
|
||||
{ Cr, { kNA, kNA, kNA, kNA, 73, 61.5, 55, 49, 44, kNA, kNA } }, // Chromium ls
|
||||
{ Cr, { kNA, kNA, kNA, kNA, 73, 61.5f, 55, 49, 44, kNA, kNA } }, // Chromium ls
|
||||
{ Cr, { kNA, kNA, kNA, kNA, 80, kNA, kNA, kNA, kNA, kNA, kNA } }, // Chromium hs
|
||||
{ Mn, { kNA, kNA, kNA, kNA, 67, 58, 53, 33, 25.5, 46, kNA } }, // Manganese ls
|
||||
{ Mn, { kNA, kNA, kNA, kNA, 83, 64.5, kNA, kNA, kNA, kNA, kNA } }, // Manganese hs
|
||||
{ Fe, { kNA, kNA, kNA, kNA, 61, 55, 58.5, kNA, 25, kNA, kNA } }, // Iron ls
|
||||
{ Fe, { kNA, kNA, kNA, kNA, 78, 64.5, kNA, kNA, kNA, kNA, kNA } }, // Iron hs
|
||||
{ Co, { kNA, kNA, kNA, kNA, 65, 54.5, kNA, kNA, kNA, kNA, kNA } }, // Cobalt ls
|
||||
{ Co, { kNA, kNA, kNA, kNA, 74.5, 61, 53, kNA, kNA, kNA, kNA } }, // Cobalt hs
|
||||
{ Mn, { kNA, kNA, kNA, kNA, 67, 58, 53, 33, 25.5f, 46, kNA } }, // Manganese ls
|
||||
{ Mn, { kNA, kNA, kNA, kNA, 83, 64.5f, kNA, kNA, kNA, kNA, kNA } }, // Manganese hs
|
||||
{ Fe, { kNA, kNA, kNA, kNA, 61, 55, 58.5f, kNA, 25, kNA, kNA } }, // Iron ls
|
||||
{ Fe, { kNA, kNA, kNA, kNA, 78, 64.5f, kNA, kNA, kNA, kNA, kNA } }, // Iron hs
|
||||
{ Co, { kNA, kNA, kNA, kNA, 65, 54.5f, kNA, kNA, kNA, kNA, kNA } }, // Cobalt ls
|
||||
{ Co, { kNA, kNA, kNA, kNA, 74.5f, 61, 53, kNA, kNA, kNA, kNA } }, // Cobalt hs
|
||||
{ Ni, { kNA, kNA, kNA, kNA, 69, 56, 48, kNA, kNA, kNA, kNA } }, // Nickel ls
|
||||
{ Ni, { kNA, kNA, kNA, kNA, kNA, 60, kNA, kNA, kNA, kNA, kNA } }, // Nickel hs
|
||||
{ Cu, { kNA, kNA, kNA, 77, 73, 54, kNA, kNA, kNA, kNA, kNA } }, // Copper
|
||||
@@ -315,10 +315,10 @@ const struct ionic_radii
|
||||
{ Zr, { kNA, kNA, kNA, kNA, kNA, kNA, 72, kNA, kNA, kNA, kNA } }, // Zirconium
|
||||
{ Nb, { kNA, kNA, kNA, kNA, kNA, 72, 68, 64, kNA, kNA, kNA } }, // Niobium
|
||||
{ Mo, { kNA, kNA, kNA, kNA, kNA, 69, 65, 61, 59, kNA, kNA } }, // Molybdenum
|
||||
{ Tc, { kNA, kNA, kNA, kNA, kNA, kNA, 64.5, 60, kNA, 56, kNA } }, // Technetium
|
||||
{ Ru, { kNA, kNA, kNA, kNA, kNA, 68, 62, 56.5, kNA, 38, 36 } }, // Ruthenium
|
||||
{ Rh, { kNA, kNA, kNA, kNA, kNA, 66.5, 60, 55, kNA, kNA, kNA } }, // Rhodium
|
||||
{ Pd, { kNA, kNA, kNA, 59, 86, 76, 61.5, kNA, kNA, kNA, kNA } }, // Palladium
|
||||
{ Tc, { kNA, kNA, kNA, kNA, kNA, kNA, 64.5f, 60, kNA, 56, kNA } }, // Technetium
|
||||
{ Ru, { kNA, kNA, kNA, kNA, kNA, 68, 62, 56.5f, kNA, 38, 36 } }, // Ruthenium
|
||||
{ Rh, { kNA, kNA, kNA, kNA, kNA, 66.5f, 60, 55, kNA, kNA, kNA } }, // Rhodium
|
||||
{ Pd, { kNA, kNA, kNA, 59, 86, 76, 61.5f, kNA, kNA, kNA, kNA } }, // Palladium
|
||||
{ Ag, { kNA, kNA, kNA, 115, 94, 75, kNA, kNA, kNA, kNA, kNA } }, // Silver
|
||||
{ Cd, { kNA, kNA, kNA, kNA, 95, kNA, kNA, kNA, kNA, kNA, kNA } }, // Cadmium
|
||||
{ In, { kNA, kNA, kNA, kNA, kNA, 80, kNA, kNA, kNA, kNA, kNA } }, // Indium
|
||||
@@ -329,48 +329,48 @@ const struct ionic_radii
|
||||
{ Xe, { kNA, kNA, kNA, kNA, kNA, kNA, kNA, kNA, kNA, kNA, 48 } }, // Xenon
|
||||
{ Cs, { kNA, kNA, kNA, 167, kNA, kNA, kNA, kNA, kNA, kNA, kNA } }, // Caesium
|
||||
{ Ba, { kNA, kNA, kNA, kNA, 135, kNA, kNA, kNA, kNA, kNA, kNA } }, // Barium
|
||||
{ La, { kNA, kNA, kNA, kNA, kNA, 103.2, kNA, kNA, kNA, kNA, kNA } }, // Lanthanum
|
||||
{ La, { kNA, kNA, kNA, kNA, kNA, 103.2f, kNA, kNA, kNA, kNA, kNA } }, // Lanthanum
|
||||
{ Ce, { kNA, kNA, kNA, kNA, kNA, 101, 87, kNA, kNA, kNA, kNA } }, // Cerium
|
||||
{ Pr, { kNA, kNA, kNA, kNA, kNA, 99, 85, kNA, kNA, kNA, kNA } }, // Praseodymium
|
||||
{ Nd, { kNA, kNA, kNA, kNA, 129, 98.3, kNA, kNA, kNA, kNA, kNA } }, // Neodymium
|
||||
{ Nd, { kNA, kNA, kNA, kNA, 129, 98.3f, kNA, kNA, kNA, kNA, kNA } }, // Neodymium
|
||||
{ Pm, { kNA, kNA, kNA, kNA, kNA, 97, kNA, kNA, kNA, kNA, kNA } }, // Promethium
|
||||
{ Sm, { kNA, kNA, kNA, kNA, 122, 95.8, kNA, kNA, kNA, kNA, kNA } }, // Samarium
|
||||
{ Eu, { kNA, kNA, kNA, kNA, 117, 94.7, kNA, kNA, kNA, kNA, kNA } }, // Europium
|
||||
{ Gd, { kNA, kNA, kNA, kNA, kNA, 93.5, kNA, kNA, kNA, kNA, kNA } }, // Gadolinium
|
||||
{ Tb, { kNA, kNA, kNA, kNA, kNA, 92.3, 76, kNA, kNA, kNA, kNA } }, // Terbium
|
||||
{ Dy, { kNA, kNA, kNA, kNA, 107, 91.2, kNA, kNA, kNA, kNA, kNA } }, // Dysprosium
|
||||
{ Ho, { kNA, kNA, kNA, kNA, kNA, 90.1, kNA, kNA, kNA, kNA, kNA } }, // Holmium
|
||||
{ Sm, { kNA, kNA, kNA, kNA, 122, 95.8f, kNA, kNA, kNA, kNA, kNA } }, // Samarium
|
||||
{ Eu, { kNA, kNA, kNA, kNA, 117, 94.7f, kNA, kNA, kNA, kNA, kNA } }, // Europium
|
||||
{ Gd, { kNA, kNA, kNA, kNA, kNA, 93.5f, kNA, kNA, kNA, kNA, kNA } }, // Gadolinium
|
||||
{ Tb, { kNA, kNA, kNA, kNA, kNA, 92.3f, 76, kNA, kNA, kNA, kNA } }, // Terbium
|
||||
{ Dy, { kNA, kNA, kNA, kNA, 107, 91.2f, kNA, kNA, kNA, kNA, kNA } }, // Dysprosium
|
||||
{ Ho, { kNA, kNA, kNA, kNA, kNA, 90.1f, kNA, kNA, kNA, kNA, kNA } }, // Holmium
|
||||
{ Er, { kNA, kNA, kNA, kNA, kNA, 89, kNA, kNA, kNA, kNA, kNA } }, // Erbium
|
||||
{ Tm, { kNA, kNA, kNA, kNA, 103, 88, kNA, kNA, kNA, kNA, kNA } }, // Thulium
|
||||
{ Yb, { kNA, kNA, kNA, kNA, 102, 86.8, kNA, kNA, kNA, kNA, kNA } }, // Ytterbium
|
||||
{ Lu, { kNA, kNA, kNA, kNA, kNA, 86.1, kNA, kNA, kNA, kNA, kNA } }, // Lutetium
|
||||
{ Yb, { kNA, kNA, kNA, kNA, 102, 86.8f, kNA, kNA, kNA, kNA, kNA } }, // Ytterbium
|
||||
{ Lu, { kNA, kNA, kNA, kNA, kNA, 86.1f, kNA, kNA, kNA, kNA, kNA } }, // Lutetium
|
||||
{ Hf, { kNA, kNA, kNA, kNA, kNA, kNA, 71, kNA, kNA, kNA, kNA } }, // Hafnium
|
||||
{ Ta, { kNA, kNA, kNA, kNA, kNA, 72, 68, 64, kNA, kNA, kNA } }, // Tantalum
|
||||
{ W, { kNA, kNA, kNA, kNA, kNA, kNA, 66, 62, 60, kNA, kNA } }, // Tungsten
|
||||
{ Re, { kNA, kNA, kNA, kNA, kNA, kNA, 63, 58, 55, 53, kNA } }, // Rhenium
|
||||
{ Os, { kNA, kNA, kNA, kNA, kNA, kNA, 63, 57.5, 54.5, 52.5, 39 } }, // Osmium
|
||||
{ Ir, { kNA, kNA, kNA, kNA, kNA, 68, 62.5, 57, kNA, kNA, kNA } }, // Iridium
|
||||
{ Pt, { kNA, kNA, kNA, kNA, 80, kNA, 62.5, 57, kNA, kNA, kNA } }, // Platinum
|
||||
{ Os, { kNA, kNA, kNA, kNA, kNA, kNA, 63, 57.5f, 54.5f, 52.5f, 39 } }, // Osmium
|
||||
{ Ir, { kNA, kNA, kNA, kNA, kNA, 68, 62.5f, 57, kNA, kNA, kNA } }, // Iridium
|
||||
{ Pt, { kNA, kNA, kNA, kNA, 80, kNA, 62.5f, 57, kNA, kNA, kNA } }, // Platinum
|
||||
{ Au, { kNA, kNA, kNA, 137, kNA, 85, kNA, 57, kNA, kNA, kNA } }, // Gold
|
||||
{ Hg, { kNA, kNA, kNA, 119, 102, kNA, kNA, kNA, kNA, kNA, kNA } }, // Mercury
|
||||
{ Tl, { kNA, kNA, kNA, 150, kNA, 88.5, kNA, kNA, kNA, kNA, kNA } }, // Thallium
|
||||
{ Pb, { kNA, kNA, kNA, kNA, 119, kNA, 77.5, kNA, kNA, kNA, kNA } }, // Lead
|
||||
{ Tl, { kNA, kNA, kNA, 150, kNA, 88.5f, kNA, kNA, kNA, kNA, kNA } }, // Thallium
|
||||
{ Pb, { kNA, kNA, kNA, kNA, 119, kNA, 77.5f, kNA, kNA, kNA, kNA } }, // Lead
|
||||
{ Bi, { kNA, kNA, kNA, kNA, kNA, 103, kNA, 76, kNA, kNA, kNA } }, // Bismuth
|
||||
{ Po, { kNA, 223, kNA, kNA, kNA, kNA, 94, kNA, 67, kNA, kNA } }, // Polonium
|
||||
{ At, { kNA, kNA, kNA, kNA, kNA, kNA, kNA, kNA, kNA, 62, kNA } }, // Astatine
|
||||
{ Fr, { kNA, kNA, kNA, 180, kNA, kNA, kNA, kNA, kNA, kNA, kNA } }, // Francium
|
||||
{ Ra, { kNA, kNA, kNA, kNA, 148, kNA, kNA, kNA, kNA, kNA, kNA } }, // Radium
|
||||
{ Ac, { kNA, kNA, kNA, kNA, kNA, 106.5, kNA, kNA, kNA, kNA, kNA } }, // Actinium
|
||||
{ Ac, { kNA, kNA, kNA, kNA, kNA, 106.5f, kNA, kNA, kNA, kNA, kNA } }, // Actinium
|
||||
{ Th, { kNA, kNA, kNA, kNA, kNA, kNA, 94, kNA, kNA, kNA, kNA } }, // Thorium
|
||||
{ Pa, { kNA, kNA, kNA, kNA, kNA, 104, 90, 78, kNA, kNA, kNA } }, // Protactinium
|
||||
{ U, { kNA, kNA, kNA, kNA, kNA, 102.5, 89, 76, 73, kNA, kNA } }, // Uranium
|
||||
{ U, { kNA, kNA, kNA, kNA, kNA, 102.5f, 89, 76, 73, kNA, kNA } }, // Uranium
|
||||
{ Np, { kNA, kNA, kNA, kNA, 110, 101, 87, 75, 72, 71, kNA } }, // Neptunium
|
||||
{ Pu, { kNA, kNA, kNA, kNA, kNA, 100, 86, 74, 71, kNA, kNA } }, // Plutonium
|
||||
{ Am, { kNA, kNA, kNA, kNA, 126, 97.5, 85, kNA, kNA, kNA, kNA } }, // Americium
|
||||
{ Am, { kNA, kNA, kNA, kNA, 126, 97.5f, 85, kNA, kNA, kNA, kNA } }, // Americium
|
||||
{ Cm, { kNA, kNA, kNA, kNA, kNA, 97, 85, kNA, kNA, kNA, kNA } }, // Curium
|
||||
{ Bk, { kNA, kNA, kNA, kNA, kNA, 96, 83, kNA, kNA, kNA, kNA } }, // Berkelium
|
||||
{ Cf, { kNA, kNA, kNA, kNA, kNA, 95, 82.1, kNA, kNA, kNA, kNA } }, // Californium
|
||||
{ Es, { kNA, kNA, kNA, kNA, kNA, 83.5, kNA, kNA, kNA, kNA, kNA } }, // Einsteinium
|
||||
{ Cf, { kNA, kNA, kNA, kNA, kNA, 95, 82.1f, kNA, kNA, kNA, kNA } }, // Californium
|
||||
{ Es, { kNA, kNA, kNA, kNA, kNA, 83.5f, kNA, kNA, kNA, kNA, kNA } }, // Einsteinium
|
||||
};
|
||||
|
||||
|
||||
@@ -1028,6 +1028,9 @@ atom_type_traits::atom_type_traits(const std::string& symbol)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (symbol == "X")
|
||||
m_info = &data::kKnownAtoms[0];
|
||||
|
||||
if (m_info == nullptr)
|
||||
throw std::invalid_argument("Not a known element: " + symbol);
|
||||
|
||||
@@ -24,14 +24,14 @@
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <numeric>
|
||||
#include <stack>
|
||||
|
||||
#include <cif++/category.hpp>
|
||||
#include <cif++/datablock.hpp>
|
||||
#include <cif++/parser.hpp>
|
||||
#include <cif++/utilities.hpp>
|
||||
|
||||
#include <numeric>
|
||||
#include <stack>
|
||||
|
||||
// TODO: Find out what the rules are exactly for linked items, the current implementation
|
||||
// is inconsistent. It all depends whether a link is satified if a field taking part in the
|
||||
// set of linked items is null at one side and not null in the other.
|
||||
@@ -595,8 +595,6 @@ category::category(const category &rhs)
|
||||
, m_columns(rhs.m_columns)
|
||||
, m_validator(rhs.m_validator)
|
||||
, m_cat_validator(rhs.m_cat_validator)
|
||||
, m_parent_links(rhs.m_parent_links)
|
||||
, m_child_links(rhs.m_child_links)
|
||||
, m_cascade(rhs.m_cascade)
|
||||
{
|
||||
for (auto r = rhs.m_head; r != nullptr; r = r->m_next)
|
||||
@@ -645,8 +643,6 @@ category &category::operator=(const category &rhs)
|
||||
|
||||
m_validator = rhs.m_validator;
|
||||
m_cat_validator = rhs.m_cat_validator;
|
||||
m_parent_links = rhs.m_parent_links;
|
||||
m_child_links = rhs.m_child_links;
|
||||
|
||||
if (m_cat_validator != nullptr)
|
||||
m_index = new category_index(this);
|
||||
@@ -983,11 +979,19 @@ bool category::validate_links() const
|
||||
|
||||
row_handle category::operator[](const key_type &key)
|
||||
{
|
||||
if (m_index == nullptr)
|
||||
throw std::logic_error("Category " + m_name + " does not have an index");
|
||||
row_handle result{};
|
||||
|
||||
auto row = m_index->find_by_value(key);
|
||||
return row != nullptr ? row_handle{ *this, *row } : row_handle{};
|
||||
if (not empty())
|
||||
{
|
||||
if (m_index == nullptr)
|
||||
throw std::logic_error("Category " + m_name + " does not have an index");
|
||||
|
||||
auto row = m_index->find_by_value(key);
|
||||
if (row != nullptr)
|
||||
result = { *this, *row };
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
@@ -1142,10 +1146,6 @@ category::iterator category::erase(iterator pos)
|
||||
row *r = rh.get_row();
|
||||
iterator result = ++pos;
|
||||
|
||||
iset keys;
|
||||
if (m_cat_validator)
|
||||
keys = iset(m_cat_validator->m_keys.begin(), m_cat_validator->m_keys.end());
|
||||
|
||||
if (m_head == nullptr)
|
||||
throw std::runtime_error("erase");
|
||||
|
||||
@@ -1174,7 +1174,7 @@ category::iterator category::erase(iterator pos)
|
||||
// in mmcif_pdbx.dic dictionary.
|
||||
//
|
||||
// For each link group in _pdbx_item_linked_group_list
|
||||
// a std::set of keys from one category is mapped to another.
|
||||
// a set of keys from one category is mapped to another.
|
||||
// If all values in a child are the same as the specified parent ones
|
||||
// the child is removed as well, recursively of course.
|
||||
|
||||
@@ -1198,25 +1198,29 @@ category::iterator category::erase(iterator pos)
|
||||
return result;
|
||||
}
|
||||
|
||||
size_t category::erase(condition &&cond)
|
||||
template<typename T>
|
||||
class save_value
|
||||
{
|
||||
size_t result = 0;
|
||||
|
||||
cond.prepare(*this);
|
||||
|
||||
auto ri = begin();
|
||||
while (ri != end())
|
||||
public:
|
||||
save_value(T &v, const T nv = {})
|
||||
: m_v(v)
|
||||
, m_sv(std::exchange(m_v, nv))
|
||||
{
|
||||
if (cond(*ri))
|
||||
{
|
||||
ri = erase(ri);
|
||||
++result;
|
||||
}
|
||||
else
|
||||
++ri;
|
||||
}
|
||||
|
||||
return result;
|
||||
~save_value()
|
||||
{
|
||||
m_v = m_sv;
|
||||
}
|
||||
|
||||
private:
|
||||
T &m_v;
|
||||
const T m_sv;
|
||||
};
|
||||
|
||||
size_t category::erase(condition &&cond)
|
||||
{
|
||||
return erase(std::move(cond), {});
|
||||
}
|
||||
|
||||
size_t category::erase(condition &&cond, std::function<void(row_handle)> &&visit)
|
||||
@@ -1225,12 +1229,26 @@ size_t category::erase(condition &&cond, std::function<void(row_handle)> &&visit
|
||||
|
||||
cond.prepare(*this);
|
||||
|
||||
std::map<category *, condition> potential_orphans;
|
||||
|
||||
auto ri = begin();
|
||||
while (ri != end())
|
||||
{
|
||||
if (cond(*ri))
|
||||
{
|
||||
visit(*ri);
|
||||
if (visit)
|
||||
visit(*ri);
|
||||
|
||||
for (auto &&[childCat, link] : m_child_links)
|
||||
{
|
||||
auto ccond = get_children_condition(*ri, *childCat);
|
||||
if (not ccond)
|
||||
continue;
|
||||
potential_orphans[childCat] = std::move(potential_orphans[childCat]) or std::move(ccond);
|
||||
}
|
||||
|
||||
save_value sv(m_validator);
|
||||
|
||||
ri = erase(ri);
|
||||
++result;
|
||||
}
|
||||
@@ -1238,6 +1256,9 @@ size_t category::erase(condition &&cond, std::function<void(row_handle)> &&visit
|
||||
++ri;
|
||||
}
|
||||
|
||||
for (auto &&[childCat, condition] : potential_orphans)
|
||||
childCat->erase_orphans(std::move(condition), *this);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -24,16 +24,15 @@
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <cif++/compound.hpp>
|
||||
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include <map>
|
||||
#include <mutex>
|
||||
#include <numeric>
|
||||
#include <shared_mutex>
|
||||
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
|
||||
#include <cif++/compound.hpp>
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
namespace cif
|
||||
@@ -223,6 +222,28 @@ bool compound::atoms_bonded(const std::string &atomId_1, const std::string &atom
|
||||
return i != m_bonds.end();
|
||||
}
|
||||
|
||||
float compound::bond_length(const std::string &atomId_1, const std::string &atomId_2) const
|
||||
{
|
||||
auto i = find_if(m_bonds.begin(), m_bonds.end(),
|
||||
[&](const compound_bond &b)
|
||||
{
|
||||
return (b.atom_id[0] == atomId_1 and b.atom_id[1] == atomId_2) or (b.atom_id[0] == atomId_2 and b.atom_id[1] == atomId_1);
|
||||
});
|
||||
|
||||
float result = std::numeric_limits<float>::max();
|
||||
|
||||
if (i != m_bonds.end())
|
||||
{
|
||||
auto a = get_atom_by_atom_id(atomId_1);
|
||||
auto b = get_atom_by_atom_id(atomId_2);
|
||||
|
||||
result = distance(point{a.x, a.y, a.z}, point{b.x, b.y, b.z});
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// known amino acids and bases
|
||||
|
||||
@@ -655,13 +676,13 @@ compound_factory::compound_factory()
|
||||
{
|
||||
auto ccd = cif::load_resource("components.cif");
|
||||
if (ccd)
|
||||
m_impl.reset(new CCD_compound_factory_impl(m_impl));
|
||||
m_impl = std::make_shared<CCD_compound_factory_impl>(m_impl);
|
||||
else if (cif::VERBOSE > 0)
|
||||
std::cerr << "CCD components.cif file was not found" << std::endl;
|
||||
|
||||
const char *clibd_mon = getenv("CLIBD_MON");
|
||||
if (clibd_mon != nullptr and fs::is_directory(clibd_mon))
|
||||
m_impl.reset(new CCP4_compound_factory_impl(clibd_mon));
|
||||
m_impl = std::make_shared<CCP4_compound_factory_impl>(clibd_mon, m_impl);
|
||||
else if (cif::VERBOSE > 0)
|
||||
std::cerr << "CCP4 monomers library not found, CLIBD_MON is not defined" << std::endl;
|
||||
}
|
||||
|
||||
@@ -63,7 +63,7 @@ namespace detail
|
||||
|
||||
condition_impl *key_equals_condition_impl::prepare(const category &c)
|
||||
{
|
||||
m_item_ix = get_column_ix(c, m_item_tag);
|
||||
m_item_ix = c.get_column_ix(m_item_tag);
|
||||
m_icase = is_column_type_uchar(c, m_item_tag);
|
||||
|
||||
if (c.get_cat_validator() != nullptr and
|
||||
@@ -76,53 +76,82 @@ namespace detail
|
||||
return this;
|
||||
}
|
||||
|
||||
condition_impl *and_condition_impl::prepare(const category &c)
|
||||
bool found_in_range(condition_impl *c, std::vector<and_condition_impl *>::iterator b, std::vector<and_condition_impl *>::iterator e)
|
||||
{
|
||||
for (auto &sub : mSub)
|
||||
sub = sub->prepare(c);
|
||||
bool result = true;
|
||||
|
||||
for (;;)
|
||||
for (auto s = b; s != e; ++s)
|
||||
{
|
||||
auto si = find_if(mSub.begin(), mSub.end(), [](condition_impl *sub) { return dynamic_cast<and_condition_impl *>(sub) != nullptr; });
|
||||
if (si == mSub.end())
|
||||
auto &cs = (*s)->m_sub;
|
||||
|
||||
if (find_if(cs.begin(), cs.end(), [c](const condition_impl *i) { return i->equals(c); }) == cs.end())
|
||||
{
|
||||
result = false;
|
||||
break;
|
||||
|
||||
and_condition_impl *sub_and = static_cast<and_condition_impl *>(*si);
|
||||
|
||||
mSub.erase(si);
|
||||
|
||||
mSub.insert(mSub.end(), sub_and->mSub.begin(), sub_and->mSub.end());
|
||||
sub_and->mSub.clear();
|
||||
delete sub_and;
|
||||
}
|
||||
}
|
||||
|
||||
return this;
|
||||
return result;
|
||||
}
|
||||
|
||||
condition_impl *and_condition_impl::combine_equal(std::vector<and_condition_impl *> &subs, or_condition_impl *oc)
|
||||
{
|
||||
and_condition_impl *and_result = nullptr;
|
||||
|
||||
auto first = subs.front();
|
||||
auto &fc = first->m_sub;
|
||||
|
||||
for (auto c : fc)
|
||||
{
|
||||
if (not found_in_range(c, subs.begin() + 1, subs.end()))
|
||||
continue;
|
||||
|
||||
if (and_result == nullptr)
|
||||
and_result = new and_condition_impl();
|
||||
|
||||
and_result->m_sub.push_back(c);
|
||||
fc.erase(remove(fc.begin(), fc.end(), c), fc.end());
|
||||
|
||||
for (auto sub : subs)
|
||||
{
|
||||
auto &ssub = sub->m_sub;
|
||||
|
||||
for (auto sc : ssub)
|
||||
{
|
||||
if (not sc->equals(c))
|
||||
continue;
|
||||
|
||||
ssub.erase(remove(ssub.begin(), ssub.end(), sc), ssub.end());
|
||||
delete sc;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (and_result != nullptr)
|
||||
{
|
||||
and_result->m_sub.push_back(oc);
|
||||
return and_result;
|
||||
}
|
||||
|
||||
return oc;
|
||||
}
|
||||
|
||||
condition_impl *or_condition_impl::prepare(const category &c)
|
||||
{
|
||||
condition_impl *result = this;
|
||||
std::vector<and_condition_impl *> and_conditions;
|
||||
|
||||
mA = mA->prepare(c);
|
||||
mB = mB->prepare(c);
|
||||
|
||||
key_equals_condition_impl *equals = dynamic_cast<key_equals_condition_impl*>(mA);
|
||||
key_is_empty_condition_impl *empty = dynamic_cast<key_is_empty_condition_impl*>(mB);
|
||||
|
||||
if (equals == nullptr and empty == nullptr)
|
||||
for (auto &sub : m_sub)
|
||||
{
|
||||
equals = dynamic_cast<key_equals_condition_impl*>(mB);
|
||||
empty = dynamic_cast<key_is_empty_condition_impl*>(mA);
|
||||
sub = sub->prepare(c);
|
||||
if (typeid(*sub) == typeid(and_condition_impl))
|
||||
and_conditions.push_back(static_cast<and_condition_impl *>(sub));
|
||||
}
|
||||
|
||||
if (equals != nullptr and empty != nullptr and equals->m_item_tag == empty->m_item_tag)
|
||||
{
|
||||
result = new detail::key_equals_or_empty_condition_impl(equals);
|
||||
result = result->prepare(c);
|
||||
delete this;
|
||||
}
|
||||
if (and_conditions.size() == m_sub.size())
|
||||
return and_condition_impl::combine_equal(and_conditions, this);
|
||||
|
||||
return result;
|
||||
return this;
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
@@ -29,6 +29,30 @@
|
||||
namespace cif
|
||||
{
|
||||
|
||||
datablock::datablock(const datablock &db)
|
||||
: std::list<category>(db)
|
||||
, m_name(db.m_name)
|
||||
, m_validator(db.m_validator)
|
||||
{
|
||||
for (auto &cat : *this)
|
||||
cat.update_links(*this);
|
||||
}
|
||||
|
||||
datablock &datablock::operator=(const datablock &db)
|
||||
{
|
||||
if (this != &db)
|
||||
{
|
||||
std::list<category>::operator=(db);
|
||||
m_name = db.m_name;
|
||||
m_validator = db.m_validator;
|
||||
|
||||
for (auto &cat : *this)
|
||||
cat.update_links(*this);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
void datablock::set_validator(const validator *v)
|
||||
{
|
||||
m_validator = v;
|
||||
|
||||
@@ -125,7 +125,7 @@ void file::load_dictionary(std::string_view name)
|
||||
|
||||
bool file::contains(std::string_view name) const
|
||||
{
|
||||
return std::find_if(begin(), end(), [name](const datablock &db) { return db.name() == name; }) != end();
|
||||
return std::find_if(begin(), end(), [name](const datablock &db) { return iequals(db.name(), name); }) != end();
|
||||
}
|
||||
|
||||
datablock &file::operator[](std::string_view name)
|
||||
|
||||
@@ -24,10 +24,10 @@
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <cassert>
|
||||
|
||||
#include <cif++/row.hpp>
|
||||
|
||||
#include <cassert>
|
||||
|
||||
namespace cif
|
||||
{
|
||||
|
||||
|
||||
592
src/model.cpp
592
src/model.cpp
@@ -34,8 +34,6 @@
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
extern int VERBOSE;
|
||||
|
||||
namespace cif::mm
|
||||
{
|
||||
|
||||
@@ -305,6 +303,25 @@ std::ostream &operator<<(std::ostream &os, const atom &atom)
|
||||
// --------------------------------------------------------------------
|
||||
// residue
|
||||
|
||||
residue::residue(structure &structure, const std::vector<atom> &atoms)
|
||||
: m_structure(&structure)
|
||||
{
|
||||
if (atoms.empty())
|
||||
throw std::runtime_error("Empty list of atoms");
|
||||
|
||||
auto &a = atoms.front();
|
||||
|
||||
m_compound_id = a.get_label_comp_id();
|
||||
m_asym_id = a.get_label_asym_id();
|
||||
m_seq_id = a.get_label_seq_id();
|
||||
m_auth_asym_id = a.get_auth_asym_id();
|
||||
m_auth_seq_id = a.get_auth_seq_id();
|
||||
m_pdb_ins_code = a.get_pdb_ins_code();
|
||||
|
||||
for (auto atom : atoms)
|
||||
m_atoms.push_back(atom);
|
||||
}
|
||||
|
||||
// residue::residue(residue &&rhs)
|
||||
// : m_structure(rhs.m_structure)
|
||||
// , m_compound_id(std::move(rhs.m_compound_id))
|
||||
@@ -601,20 +618,20 @@ float monomer::phi() const
|
||||
{
|
||||
float result = 360;
|
||||
|
||||
try
|
||||
if (m_index > 0)
|
||||
{
|
||||
if (m_index > 0)
|
||||
auto &prev = m_polymer->operator[](m_index - 1);
|
||||
if (prev.m_seq_id + 1 == m_seq_id)
|
||||
{
|
||||
auto &prev = m_polymer->operator[](m_index - 1);
|
||||
if (prev.m_seq_id + 1 == m_seq_id)
|
||||
result = static_cast<float>(dihedral_angle(prev.C().get_location(), N().get_location(), CAlpha().get_location(), C().get_location()));
|
||||
auto a1 = prev.C();
|
||||
auto a2 = N();
|
||||
auto a3 = CAlpha();
|
||||
auto a4 = C();
|
||||
|
||||
if (a1 and a2 and a3 and a4)
|
||||
result = dihedral_angle(a1.get_location(), a2.get_location(), a3.get_location(), a4.get_location());
|
||||
}
|
||||
}
|
||||
catch (const std::exception &ex)
|
||||
{
|
||||
if (VERBOSE > 0)
|
||||
std::cerr << ex.what() << std::endl;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -623,20 +640,20 @@ float monomer::psi() const
|
||||
{
|
||||
float result = 360;
|
||||
|
||||
try
|
||||
if (m_index + 1 < m_polymer->size())
|
||||
{
|
||||
if (m_index + 1 < m_polymer->size())
|
||||
auto &next = m_polymer->operator[](m_index + 1);
|
||||
if (m_seq_id + 1 == next.m_seq_id)
|
||||
{
|
||||
auto &next = m_polymer->operator[](m_index + 1);
|
||||
if (m_seq_id + 1 == next.m_seq_id)
|
||||
result = static_cast<float>(dihedral_angle(N().get_location(), CAlpha().get_location(), C().get_location(), next.N().get_location()));
|
||||
auto a1 = N();
|
||||
auto a2 = CAlpha();
|
||||
auto a3 = C();
|
||||
auto a4 = next.N();
|
||||
|
||||
if (a1 and a2 and a3 and a4)
|
||||
result = dihedral_angle(a1.get_location(), a2.get_location(), a3.get_location(), a4.get_location());
|
||||
}
|
||||
}
|
||||
catch (const std::exception &ex)
|
||||
{
|
||||
if (VERBOSE > 0)
|
||||
std::cerr << ex.what() << std::endl;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -918,30 +935,30 @@ float monomer::omega(const monomer &a, const monomer &b)
|
||||
{
|
||||
float result = 360;
|
||||
|
||||
try
|
||||
{
|
||||
auto a1 = a.get_atom_by_atom_id("CA");
|
||||
auto a2 = a.get_atom_by_atom_id("C");
|
||||
auto a3 = b.get_atom_by_atom_id("N");
|
||||
auto a4 = b.get_atom_by_atom_id("CA");
|
||||
|
||||
if (a1 and a2 and a3 and a4)
|
||||
result = static_cast<float>(dihedral_angle(
|
||||
a.get_atom_by_atom_id("CA").get_location(),
|
||||
a.get_atom_by_atom_id("C").get_location(),
|
||||
b.get_atom_by_atom_id("N").get_location(),
|
||||
b.get_atom_by_atom_id("CA").get_location()));
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
}
|
||||
a1.get_location(),
|
||||
a2.get_location(),
|
||||
a3.get_location(),
|
||||
a4.get_location()));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool monomer::is_cis(const monomer &a, const monomer &b)
|
||||
{
|
||||
return omega(a, b) < 30.0f;
|
||||
return std::abs(omega(a, b)) < 30.0f;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// polymer
|
||||
|
||||
polymer::polymer(const structure &s, const std::string &entityID, const std::string &asym_id, const std::string &auth_asym_id)
|
||||
polymer::polymer(structure &s, const std::string &entityID, const std::string &asym_id, const std::string &auth_asym_id)
|
||||
: m_structure(const_cast<structure *>(&s))
|
||||
, m_entity_id(entityID)
|
||||
, m_asym_id(asym_id)
|
||||
@@ -957,8 +974,12 @@ polymer::polymer(const structure &s, const std::string &entityID, const std::str
|
||||
for (auto r : poly_seq_scheme.find("asym_id"_key == asym_id))
|
||||
{
|
||||
int seqID;
|
||||
std::optional<int> pdbSeqNum;
|
||||
std::string compoundID, authSeqID, pdbInsCode;
|
||||
cif::tie(seqID, authSeqID, compoundID, pdbInsCode) = r.get("seq_id", "auth_seq_num", "mon_id", "pdb_ins_code");
|
||||
cif::tie(seqID, authSeqID, compoundID, pdbInsCode, pdbSeqNum) = r.get("seq_id", "auth_seq_num", "mon_id", "pdb_ins_code", "pdb_seq_num");
|
||||
|
||||
if (authSeqID.empty() and pdbSeqNum.has_value())
|
||||
authSeqID = std::to_string(*pdbSeqNum);
|
||||
|
||||
size_t index = size();
|
||||
|
||||
@@ -1027,7 +1048,7 @@ polymer::polymer(const structure &s, const std::string &entityID, const std::str
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
sugar::sugar(const branch &branch, const std::string &compoundID,
|
||||
sugar::sugar(branch &branch, const std::string &compoundID,
|
||||
const std::string &asym_id, int authSeqID)
|
||||
: residue(branch.get_structure(), compoundID, asym_id, 0, asym_id, std::to_string(authSeqID), "")
|
||||
, m_branch(&branch)
|
||||
@@ -1095,9 +1116,39 @@ std::string sugar::name() const
|
||||
return result;
|
||||
}
|
||||
|
||||
branch::branch(structure &structure, const std::string &asym_id)
|
||||
cif::mm::atom sugar::add_atom(row_initializer atom_info)
|
||||
{
|
||||
auto &db = m_structure->get_datablock();
|
||||
auto &atom_site = db["atom_site"];
|
||||
|
||||
auto atom_id = atom_site.get_unique_id("");
|
||||
|
||||
atom_info.set_value({"group_PDB", "HETATM"});
|
||||
atom_info.set_value({"id", atom_id});
|
||||
atom_info.set_value({"label_entity_id", m_branch->get_entity_id()});
|
||||
atom_info.set_value({"label_asym_id", m_branch->get_asym_id()});
|
||||
atom_info.set_value({"label_comp_id", m_compound_id});
|
||||
atom_info.set_value({"label_seq_id", "."});
|
||||
atom_info.set_value({"label_alt_id", "."});
|
||||
atom_info.set_value({"auth_asym_id", m_branch->get_asym_id()});
|
||||
atom_info.set_value({"auth_comp_id", m_compound_id});
|
||||
atom_info.set_value({"auth_seq_id", m_auth_seq_id});
|
||||
atom_info.set_value({"occupancy", 1.0, 2});
|
||||
atom_info.set_value({"B_iso_or_equiv", 30.0, 2});
|
||||
atom_info.set_value({"pdbx_PDB_model_num", 1});
|
||||
|
||||
auto row = atom_site.emplace(std::move(atom_info));
|
||||
auto result = m_structure->emplace_atom(db, row);
|
||||
|
||||
residue::add_atom(result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
branch::branch(structure &structure, const std::string &asym_id, const std::string &entity_id)
|
||||
: m_structure(&structure)
|
||||
, m_asym_id(asym_id)
|
||||
, m_entity_id(entity_id)
|
||||
{
|
||||
using namespace literals;
|
||||
|
||||
@@ -1106,7 +1157,7 @@ branch::branch(structure &structure, const std::string &asym_id)
|
||||
auto &branch_scheme = db["pdbx_branch_scheme"];
|
||||
auto &branch_link = db["pdbx_entity_branch_link"];
|
||||
|
||||
for (const auto &entity_id : struct_asym.find<std::string>("id"_key == asym_id, "entity_id"))
|
||||
for (const auto &asym_entity_id : struct_asym.find<std::string>("id"_key == asym_id, "entity_id"))
|
||||
{
|
||||
for (const auto &[comp_id, num] : branch_scheme.find<std::string, int>(
|
||||
"asym_id"_key == asym_id, "mon_id", "pdb_seq_num"))
|
||||
@@ -1115,7 +1166,7 @@ branch::branch(structure &structure, const std::string &asym_id)
|
||||
}
|
||||
|
||||
for (const auto &[num1, num2, atom1, atom2] : branch_link.find<size_t, size_t, std::string, std::string>(
|
||||
"entity_id"_key == entity_id, "entity_branch_list_num_1", "entity_branch_list_num_2", "atom_id_1", "atom_id_2"))
|
||||
"entity_id"_key == asym_entity_id, "entity_branch_list_num_1", "entity_branch_list_num_2", "atom_id_1", "atom_id_2"))
|
||||
{
|
||||
// if (not iequals(atom1, "c1"))
|
||||
// throw std::runtime_error("invalid pdbx_entity_branch_link");
|
||||
@@ -1155,11 +1206,92 @@ void branch::link_atoms()
|
||||
}
|
||||
}
|
||||
|
||||
sugar &branch::get_sugar_by_num(int nr)
|
||||
{
|
||||
auto i = find_if(begin(), end(), [nr](const sugar &s) { return s.num() == nr; });
|
||||
if (i == end())
|
||||
throw std::out_of_range("Sugar with num " + std::to_string(nr) + " not found in branch " + m_asym_id);
|
||||
|
||||
return *i;
|
||||
}
|
||||
|
||||
std::string branch::name() const
|
||||
{
|
||||
return empty() ? "" : name(front());
|
||||
}
|
||||
|
||||
sugar &branch::construct_sugar(const std::string &compound_id)
|
||||
{
|
||||
auto &db = m_structure->get_datablock();
|
||||
|
||||
auto compound = compound_factory::instance().create(compound_id);
|
||||
if (compound == nullptr)
|
||||
throw std::runtime_error("Trying to insert unknown compound " + compound_id + " (not found in CCD)");
|
||||
|
||||
auto &chemComp = db["chem_comp"];
|
||||
auto r = chemComp.find(key("id") == compound_id);
|
||||
if (r.empty())
|
||||
{
|
||||
chemComp.emplace({
|
||||
{"id", compound_id},
|
||||
{"name", compound->name()},
|
||||
{"formula", compound->formula()},
|
||||
{"formula_weight", compound->formula_weight()},
|
||||
{"type", compound->type()}});
|
||||
}
|
||||
|
||||
sugar &result = emplace_back(*this, compound_id, m_asym_id, static_cast<int>(size() + 1));
|
||||
|
||||
db["pdbx_branch_scheme"].emplace({
|
||||
{"asym_id", result.get_asym_id()},
|
||||
{"entity_id", result.get_entity_id()},
|
||||
{"num", result.num()},
|
||||
{"mon_id", result.get_compound_id()},
|
||||
|
||||
{"pdb_asym_id", result.get_asym_id()},
|
||||
{"pdb_seq_num", result.num()},
|
||||
{"pdb_mon_id", result.get_compound_id()},
|
||||
|
||||
{"auth_asym_id", result.get_auth_asym_id()},
|
||||
{"auth_mon_id", result.get_compound_id()},
|
||||
{"auth_seq_num", result.get_auth_seq_id()},
|
||||
|
||||
{"hetero", "n"}
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
sugar &branch::construct_sugar(const std::string &compound_id, const std::string &atom_id,
|
||||
int linked_sugar_nr, const std::string &linked_atom_id)
|
||||
{
|
||||
auto &result = construct_sugar(compound_id);
|
||||
|
||||
auto &linked = get_sugar_by_num(linked_sugar_nr);
|
||||
result.set_link(linked.get_atom_by_atom_id(linked_atom_id));
|
||||
|
||||
auto &db = m_structure->get_datablock();
|
||||
|
||||
auto &pdbx_entity_branch_link = db["pdbx_entity_branch_link"];
|
||||
auto linkID = pdbx_entity_branch_link.get_unique_id("");
|
||||
|
||||
db["pdbx_entity_branch_link"].emplace({
|
||||
{ "link_id", linkID },
|
||||
{ "entity_id", get_entity_id() },
|
||||
{ "entity_branch_list_num_1", result.num() },
|
||||
{ "comp_id_1", compound_id },
|
||||
{ "atom_id_1", atom_id },
|
||||
{ "leaving_atom_id_1", "O1" }, /// TODO: Need to fix this!
|
||||
{ "entity_branch_list_num_2", linked.num() },
|
||||
{ "comp_id_2", linked.get_compound_id() },
|
||||
{ "atom_id_2", linked_atom_id },
|
||||
{ "leaving_atom_id_2", "." },
|
||||
{ "value_order", "sing" }
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string branch::name(const sugar &s) const
|
||||
{
|
||||
using namespace literals;
|
||||
@@ -1279,10 +1411,10 @@ void structure::load_data()
|
||||
|
||||
auto &branchScheme = m_db["pdbx_branch_scheme"];
|
||||
|
||||
for (const auto &asym_id : branchScheme.rows<std::string>("asym_id"))
|
||||
for (const auto &[asym_id, entity_id] : branchScheme.rows<std::string,std::string>("asym_id", "entity_id"))
|
||||
{
|
||||
if (m_branches.empty() or m_branches.back().get_asym_id() != asym_id)
|
||||
m_branches.emplace_back(*this, asym_id);
|
||||
m_branches.emplace_back(*this, asym_id, entity_id);
|
||||
}
|
||||
|
||||
auto &nonPolyScheme = m_db["pdbx_nonpoly_scheme"];
|
||||
@@ -1514,6 +1646,11 @@ polymer &structure::get_polymer_by_asym_id(const std::string &asym_id)
|
||||
throw std::runtime_error("polymer with asym id " + asym_id + " not found");
|
||||
}
|
||||
|
||||
residue &structure::create_residue(const std::vector<atom> &atoms)
|
||||
{
|
||||
return m_non_polymers.emplace_back(*this, atoms);
|
||||
}
|
||||
|
||||
residue &structure::get_residue(const std::string &asym_id, int seqID, const std::string &authSeqID)
|
||||
{
|
||||
if (seqID == 0)
|
||||
@@ -1643,7 +1780,7 @@ std::string structure::insert_compound(const std::string &compoundID, bool is_en
|
||||
{
|
||||
auto &pdbxEntityNonpoly = m_db["pdbx_entity_nonpoly"];
|
||||
|
||||
entity_id = pdbxEntityNonpoly.find1<std::string>("comp_id"_key == compoundID, "entity_id");
|
||||
entity_id = pdbxEntityNonpoly.find_first<std::string>("comp_id"_key == compoundID, "entity_id");
|
||||
|
||||
if (entity_id.empty())
|
||||
{
|
||||
@@ -1688,7 +1825,10 @@ atom &structure::emplace_atom(atom &&atom)
|
||||
R = i - 1;
|
||||
}
|
||||
|
||||
m_atom_index.insert(m_atom_index.begin() + R + 1, m_atoms.size());
|
||||
if (R == -1) // msvc...
|
||||
m_atom_index.insert(m_atom_index.begin(), m_atoms.size());
|
||||
else
|
||||
m_atom_index.insert(m_atom_index.begin() + R + 1, m_atoms.size());
|
||||
|
||||
// make sure the atom_type is known
|
||||
auto &atom_type = m_db["atom_type"];
|
||||
@@ -1814,7 +1954,7 @@ void structure::change_residue(residue &res, const std::string &newCompound,
|
||||
// create a copy of the entity first
|
||||
auto &entity = m_db["entity"];
|
||||
|
||||
entityID = entity.find1<std::string>("type"_key == "non-polymer" and "pdbx_description"_key == compound->name(), "id");
|
||||
entityID = entity.find_first<std::string>("type"_key == "non-polymer" and "pdbx_description"_key == compound->name(), "id");
|
||||
|
||||
if (entityID.empty())
|
||||
{
|
||||
@@ -1895,6 +2035,51 @@ void structure::change_residue(residue &res, const std::string &newCompound,
|
||||
}
|
||||
}
|
||||
|
||||
void structure::remove_residue(const std::string &asym_id, int seq_id, const std::string &auth_seq_id)
|
||||
{
|
||||
if (seq_id == 0)
|
||||
{
|
||||
for (auto &res : m_non_polymers)
|
||||
{
|
||||
if (res.get_asym_id() == asym_id and (auth_seq_id.empty() or res.get_auth_seq_id() == auth_seq_id))
|
||||
{
|
||||
remove_residue(res);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (auto &poly : m_polymers)
|
||||
{
|
||||
if (poly.get_asym_id() != asym_id)
|
||||
continue;
|
||||
|
||||
for (auto &res : poly)
|
||||
{
|
||||
if (res.get_seq_id() == seq_id)
|
||||
{
|
||||
remove_residue(res);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (auto &branch : m_branches)
|
||||
{
|
||||
if (branch.get_asym_id() != asym_id)
|
||||
continue;
|
||||
|
||||
for (auto &sugar : branch)
|
||||
{
|
||||
if (sugar.get_asym_id() == asym_id and sugar.get_auth_seq_id() == auth_seq_id)
|
||||
{
|
||||
remove_residue(sugar);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void structure::remove_residue(residue &res)
|
||||
{
|
||||
using namespace literals;
|
||||
@@ -2181,55 +2366,18 @@ std::string structure::create_non_poly(const std::string &entity_id, std::vector
|
||||
return asym_id;
|
||||
}
|
||||
|
||||
branch &structure::create_branch(std::vector<row_initializer> atoms)
|
||||
branch &structure::create_branch()
|
||||
{
|
||||
// sanity check
|
||||
for (auto &nag_atom : atoms)
|
||||
{
|
||||
for (const auto &[name, value] : nag_atom)
|
||||
{
|
||||
if (name == "label_comp_id" and value != "NAG")
|
||||
throw std::logic_error("The first sugar in a branch should be a NAG");
|
||||
}
|
||||
}
|
||||
|
||||
using namespace literals;
|
||||
|
||||
auto &entity = m_db["entity"];
|
||||
auto &struct_asym = m_db["struct_asym"];
|
||||
std::string asym_id = struct_asym.get_unique_id();
|
||||
|
||||
auto &branch = m_branches.emplace_back(*this, asym_id);
|
||||
auto &sugar = branch.emplace_back(branch, "NAG", asym_id, 1);
|
||||
auto tmp_entity_id = m_db["entity"].get_unique_id("");
|
||||
auto entity_id = entity.get_unique_id("");
|
||||
auto asym_id = struct_asym.get_unique_id();
|
||||
|
||||
auto &atom_site = m_db["atom_site"];
|
||||
|
||||
for (auto &atom : atoms)
|
||||
{
|
||||
auto atom_id = atom_site.get_unique_id("");
|
||||
|
||||
atom.set_value("id", atom_id);
|
||||
atom.set_value("label_asym_id", asym_id);
|
||||
atom.set_value("auth_asym_id", asym_id);
|
||||
atom.set_value("label_entity_id", tmp_entity_id);
|
||||
atom.set_value({ "auth_seq_id", 1 });
|
||||
|
||||
atom.set_value_if_empty({"group_PDB", "HETATM"});
|
||||
atom.set_value_if_empty({"label_comp_id", "NAG"});
|
||||
atom.set_value_if_empty({"label_seq_id", "."});
|
||||
atom.set_value_if_empty({"auth_comp_id", "NAG"});
|
||||
atom.set_value_if_empty({"pdbx_PDB_model_num", 1});
|
||||
atom.set_value_if_empty({"label_alt_id", ""});
|
||||
|
||||
auto row = atom_site.emplace(atom.begin(), atom.end());
|
||||
|
||||
auto &newAtom = emplace_atom(std::make_shared<atom::atom_impl>(m_db, atom_id));
|
||||
sugar.add_atom(newAtom);
|
||||
}
|
||||
|
||||
// now we can create the entity and get the real ID
|
||||
auto entity_id = create_entity_for_branch(branch);
|
||||
assert(not entity_id.empty());
|
||||
entity.emplace({
|
||||
{"id", entity_id},
|
||||
{"type", "branched"}
|
||||
});
|
||||
|
||||
struct_asym.emplace({
|
||||
{"id", asym_id},
|
||||
@@ -2239,131 +2387,183 @@ branch &structure::create_branch(std::vector<row_initializer> atoms)
|
||||
{"details", "?"}
|
||||
});
|
||||
|
||||
for (auto &a : sugar.atoms())
|
||||
a.set_property("label_entity_id", entity_id);
|
||||
|
||||
m_db["pdbx_branch_scheme"].emplace({
|
||||
{"asym_id", asym_id},
|
||||
{"entity_id", entity_id},
|
||||
{"num", 1},
|
||||
{"mon_id", "NAG"},
|
||||
|
||||
{"pdb_asym_id", asym_id},
|
||||
{"pdb_seq_num", 1},
|
||||
{"pdb_mon_id", "NAG"},
|
||||
|
||||
// TODO: need fix, collect from nag_atoms?
|
||||
{"auth_asym_id", asym_id},
|
||||
{"auth_mon_id", "NAG"},
|
||||
{"auth_seq_num", 1},
|
||||
|
||||
{"hetero", "n"}
|
||||
});
|
||||
|
||||
return branch;
|
||||
return m_branches.emplace_back(*this, asym_id, entity_id);
|
||||
}
|
||||
|
||||
branch &structure::extend_branch(const std::string &asym_id, std::vector<row_initializer> atom_info,
|
||||
int link_sugar, const std::string &link_atom)
|
||||
{
|
||||
// sanity check
|
||||
std::string compoundID;
|
||||
// branch &structure::create_branch(std::vector<row_initializer> atoms)
|
||||
// {
|
||||
// // // sanity check
|
||||
// // for (auto &nag_atom : atoms)
|
||||
// // {
|
||||
// // for (const auto &[name, value] : nag_atom)
|
||||
// // {
|
||||
// // if (name == "label_comp_id" and value != "NAG")
|
||||
// // throw std::logic_error("The first sugar in a branch should be a NAG");
|
||||
// // }
|
||||
// // }
|
||||
|
||||
for (auto &atom : atom_info)
|
||||
{
|
||||
for (const auto &[name, value] : atom)
|
||||
{
|
||||
if (name != "label_comp_id")
|
||||
continue;
|
||||
// // using namespace literals;
|
||||
|
||||
if (compoundID.empty())
|
||||
compoundID = value;
|
||||
else if (value != compoundID)
|
||||
throw std::logic_error("All atoms should be of the same type");
|
||||
}
|
||||
}
|
||||
// // auto &branch = create_branch();
|
||||
// // auto asym_id = branch.get_asym_id();
|
||||
// // auto entity_id = branch.get_entity_id();
|
||||
|
||||
using namespace literals;
|
||||
// // auto &sugar = branch.emplace_back(branch, "NAG", asym_id, 1);
|
||||
|
||||
// auto &branch = m_branches.emplace_back(*this, asym_id);
|
||||
auto tmp_entity_id = m_db["entity"].get_unique_id("");
|
||||
// // auto &atom_site = m_db["atom_site"];
|
||||
|
||||
auto &atom_site = m_db["atom_site"];
|
||||
// // for (auto &atom : atoms)
|
||||
// // {
|
||||
// // auto atom_id = atom_site.get_unique_id("");
|
||||
|
||||
auto bi = std::find_if(m_branches.begin(), m_branches.end(), [asym_id](branch &b)
|
||||
{ return b.get_asym_id() == asym_id; });
|
||||
if (bi == m_branches.end())
|
||||
throw std::logic_error("Create a branch first!");
|
||||
// // atom.set_value("id", atom_id);
|
||||
// // atom.set_value("label_asym_id", asym_id);
|
||||
// // atom.set_value("auth_asym_id", asym_id);
|
||||
// // atom.set_value("label_entity_id", entity_id);
|
||||
// // atom.set_value({ "auth_seq_id", 1 });
|
||||
|
||||
branch &branch = *bi;
|
||||
// // atom.set_value_if_empty({"group_PDB", "HETATM"});
|
||||
// // atom.set_value_if_empty({"label_comp_id", "NAG"});
|
||||
// // atom.set_value_if_empty({"label_seq_id", "."});
|
||||
// // atom.set_value_if_empty({"auth_comp_id", "NAG"});
|
||||
// // atom.set_value_if_empty({"pdbx_PDB_model_num", 1});
|
||||
// // atom.set_value_if_empty({"label_alt_id", ""});
|
||||
|
||||
int sugarNum = static_cast<int>(branch.size() + 1);
|
||||
// // auto row = atom_site.emplace(atom.begin(), atom.end());
|
||||
|
||||
auto &sugar = branch.emplace_back(branch, compoundID, asym_id, sugarNum);
|
||||
// // auto &newAtom = emplace_atom(std::make_shared<atom::atom_impl>(m_db, atom_id));
|
||||
// // sugar.add_atom(newAtom);
|
||||
// // }
|
||||
|
||||
for (auto &atom : atom_info)
|
||||
{
|
||||
auto atom_id = atom_site.get_unique_id("");
|
||||
// // // // now we can create the entity and get the real ID
|
||||
// // // auto entity_id = create_entity_for_branch(branch);
|
||||
// // // assert(not entity_id.empty());
|
||||
|
||||
atom.set_value("id", atom_id);
|
||||
atom.set_value("label_asym_id", asym_id);
|
||||
atom.set_value("auth_asym_id", asym_id);
|
||||
atom.set_value("label_entity_id", tmp_entity_id);
|
||||
atom.set_value({"auth_seq_id", sugarNum });
|
||||
// // for (auto &a : sugar.atoms())
|
||||
// // a.set_property("label_entity_id", entity_id);
|
||||
|
||||
atom.set_value_if_empty({"group_PDB", "HETATM"});
|
||||
atom.set_value_if_empty({"label_comp_id", compoundID});
|
||||
atom.set_value_if_empty({"auth_comp_id", compoundID});
|
||||
atom.set_value_if_empty({"pdbx_PDB_model_num", 1});
|
||||
atom.set_value_if_empty({"label_alt_id", ""});
|
||||
// // m_db["pdbx_branch_scheme"].emplace({
|
||||
// // {"asym_id", asym_id},
|
||||
// // {"entity_id", entity_id},
|
||||
// // {"num", 1},
|
||||
// // {"mon_id", "NAG"},
|
||||
|
||||
auto row = atom_site.emplace(atom.begin(), atom.end());
|
||||
// // {"pdb_asym_id", asym_id},
|
||||
// // {"pdb_seq_num", 1},
|
||||
// // {"pdb_mon_id", "NAG"},
|
||||
|
||||
auto &newAtom = emplace_atom(std::make_shared<atom::atom_impl>(m_db, atom_id));
|
||||
sugar.add_atom(newAtom);
|
||||
}
|
||||
// // // TODO: need fix, collect from nag_atoms?
|
||||
// // {"auth_asym_id", asym_id},
|
||||
// // {"auth_mon_id", "NAG"},
|
||||
// // {"auth_seq_num", 1},
|
||||
|
||||
sugar.set_link(branch.at(link_sugar - 1).get_atom_by_atom_id(link_atom));
|
||||
// // {"hetero", "n"}
|
||||
// // });
|
||||
|
||||
auto entity_id = create_entity_for_branch(branch);
|
||||
// // return branch;
|
||||
// }
|
||||
|
||||
// Update the entity id of the asym
|
||||
auto &struct_asym = m_db["struct_asym"];
|
||||
auto r = struct_asym.find1("id"_key == asym_id);
|
||||
r["entity_id"] = entity_id;
|
||||
// branch &structure::extend_branch(const std::string &asym_id, std::vector<row_initializer> atom_info,
|
||||
// int link_sugar, const std::string &link_atom)
|
||||
// {
|
||||
// // // sanity check
|
||||
// // std::string compoundID;
|
||||
|
||||
for (auto &s2 : branch)
|
||||
{
|
||||
for (auto atom : s2.atoms())
|
||||
atom.set_property("label_entity_id", entity_id);
|
||||
}
|
||||
// // for (auto &atom : atom_info)
|
||||
// // {
|
||||
// // for (const auto &[name, value] : atom)
|
||||
// // {
|
||||
// // if (name != "label_comp_id")
|
||||
// // continue;
|
||||
|
||||
auto &pdbx_branch_scheme = m_db["pdbx_branch_scheme"];
|
||||
pdbx_branch_scheme.erase("asym_id"_key == asym_id);
|
||||
// // if (compoundID.empty())
|
||||
// // compoundID = value;
|
||||
// // else if (value != compoundID)
|
||||
// // throw std::logic_error("All atoms should be of the same type");
|
||||
// // }
|
||||
// // }
|
||||
|
||||
for (auto &s2 : branch)
|
||||
{
|
||||
pdbx_branch_scheme.emplace({
|
||||
{"asym_id", asym_id},
|
||||
{"entity_id", entity_id},
|
||||
{"num", s2.num()},
|
||||
{"mon_id", s2.get_compound_id()},
|
||||
// // using namespace literals;
|
||||
|
||||
{"pdb_asym_id", asym_id},
|
||||
{"pdb_seq_num", s2.num()},
|
||||
{"pdb_mon_id", s2.get_compound_id()},
|
||||
// // // auto &branch = m_branches.emplace_back(*this, asym_id);
|
||||
// // auto tmp_entity_id = m_db["entity"].get_unique_id("");
|
||||
|
||||
// TODO: need fix, collect from nag_atoms?
|
||||
{"auth_asym_id", asym_id},
|
||||
{"auth_mon_id", s2.get_compound_id()},
|
||||
{"auth_seq_num", s2.get_auth_seq_id()},
|
||||
// // auto &atom_site = m_db["atom_site"];
|
||||
|
||||
{"hetero", "n"}
|
||||
});
|
||||
}
|
||||
// // auto bi = std::find_if(m_branches.begin(), m_branches.end(), [asym_id](branch &b)
|
||||
// // { return b.get_asym_id() == asym_id; });
|
||||
// // if (bi == m_branches.end())
|
||||
// // throw std::logic_error("Create a branch first!");
|
||||
|
||||
return branch;
|
||||
}
|
||||
// // branch &branch = *bi;
|
||||
|
||||
// // int sugarNum = static_cast<int>(branch.size() + 1);
|
||||
|
||||
// // auto &sugar = branch.emplace_back(branch, compoundID, asym_id, sugarNum);
|
||||
|
||||
// // for (auto &atom : atom_info)
|
||||
// // {
|
||||
// // auto atom_id = atom_site.get_unique_id("");
|
||||
|
||||
// // atom.set_value("id", atom_id);
|
||||
// // atom.set_value("label_asym_id", asym_id);
|
||||
// // atom.set_value("auth_asym_id", asym_id);
|
||||
// // atom.set_value("label_entity_id", tmp_entity_id);
|
||||
// // atom.set_value({"auth_seq_id", sugarNum });
|
||||
|
||||
// // atom.set_value_if_empty({"group_PDB", "HETATM"});
|
||||
// // atom.set_value_if_empty({"label_comp_id", compoundID});
|
||||
// // atom.set_value_if_empty({"auth_comp_id", compoundID});
|
||||
// // atom.set_value_if_empty({"pdbx_PDB_model_num", 1});
|
||||
// // atom.set_value_if_empty({"label_alt_id", ""});
|
||||
|
||||
// // auto row = atom_site.emplace(atom.begin(), atom.end());
|
||||
|
||||
// // auto &newAtom = emplace_atom(std::make_shared<atom::atom_impl>(m_db, atom_id));
|
||||
// // sugar.add_atom(newAtom);
|
||||
// // }
|
||||
|
||||
// // sugar.set_link(branch.at(link_sugar - 1).get_atom_by_atom_id(link_atom));
|
||||
|
||||
// // auto entity_id = create_entity_for_branch(branch);
|
||||
|
||||
// // // Update the entity id of the asym
|
||||
// // auto &struct_asym = m_db["struct_asym"];
|
||||
// // auto r = struct_asym.find1("id"_key == asym_id);
|
||||
// // r["entity_id"] = entity_id;
|
||||
|
||||
// // for (auto &s2 : branch)
|
||||
// // {
|
||||
// // for (auto atom : s2.atoms())
|
||||
// // atom.set_property("label_entity_id", entity_id);
|
||||
// // }
|
||||
|
||||
// // auto &pdbx_branch_scheme = m_db["pdbx_branch_scheme"];
|
||||
// // pdbx_branch_scheme.erase("asym_id"_key == asym_id);
|
||||
|
||||
// // for (auto &s2 : branch)
|
||||
// // {
|
||||
// // pdbx_branch_scheme.emplace({
|
||||
// // {"asym_id", asym_id},
|
||||
// // {"entity_id", entity_id},
|
||||
// // {"num", s2.num()},
|
||||
// // {"mon_id", s2.get_compound_id()},
|
||||
|
||||
// // {"pdb_asym_id", asym_id},
|
||||
// // {"pdb_seq_num", s2.num()},
|
||||
// // {"pdb_mon_id", s2.get_compound_id()},
|
||||
|
||||
// // // TODO: need fix, collect from nag_atoms?
|
||||
// // {"auth_asym_id", asym_id},
|
||||
// // {"auth_mon_id", s2.get_compound_id()},
|
||||
// // {"auth_seq_num", s2.get_auth_seq_id()},
|
||||
|
||||
// // {"hetero", "n"}
|
||||
// // });
|
||||
// // }
|
||||
|
||||
// // return branch;
|
||||
// }
|
||||
|
||||
std::string structure::create_entity_for_branch(branch &branch)
|
||||
{
|
||||
@@ -2373,7 +2573,7 @@ std::string structure::create_entity_for_branch(branch &branch)
|
||||
|
||||
auto &entity = m_db["entity"];
|
||||
|
||||
std::string entityID = entity.find1<std::string>("type"_key == "branched" and "pdbx_description"_key == entityName, "id");
|
||||
std::string entityID = entity.find_first<std::string>("type"_key == "branched" and "pdbx_description"_key == entityName, "id");
|
||||
|
||||
if (entityID.empty())
|
||||
{
|
||||
@@ -2382,11 +2582,13 @@ std::string structure::create_entity_for_branch(branch &branch)
|
||||
if (VERBOSE)
|
||||
std::cout << "Creating new entity " << entityID << " for branched sugar " << entityName << std::endl;
|
||||
|
||||
entity.emplace({{"id", entityID},
|
||||
entity.emplace({
|
||||
{"id", entityID},
|
||||
{"type", "branched"},
|
||||
{"src_method", "man"},
|
||||
{"pdbx_description", entityName},
|
||||
{"formula_weight", branch.weight()}});
|
||||
|
||||
auto &pdbx_entity_branch_list = m_db["pdbx_entity_branch_list"];
|
||||
for (auto &sugar : branch)
|
||||
{
|
||||
@@ -2575,4 +2777,14 @@ void structure::validate_atoms() const
|
||||
assert(atoms.empty());
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
void reconstruct_pdbx(datablock &db)
|
||||
{
|
||||
if (db.get("atom_site") == nullptr)
|
||||
throw std::runtime_error("Cannot reconstruct PDBx file, atom data missing");
|
||||
|
||||
|
||||
}
|
||||
|
||||
} // namespace pdbx
|
||||
|
||||
@@ -24,23 +24,17 @@
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <cif++/utilities.hpp>
|
||||
#include <cif++/forward_decl.hpp>
|
||||
#include <cif++/parser.hpp>
|
||||
#include <cif++/file.hpp>
|
||||
|
||||
#include <cassert>
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <regex>
|
||||
#include <stack>
|
||||
|
||||
#include <cif++/utilities.hpp>
|
||||
|
||||
#include <cif++/forward_decl.hpp>
|
||||
#include <cif++/parser.hpp>
|
||||
#include <cif++/file.hpp>
|
||||
|
||||
namespace cif
|
||||
{
|
||||
extern int VERBOSE;
|
||||
}
|
||||
|
||||
namespace cif
|
||||
{
|
||||
|
||||
@@ -380,18 +374,13 @@ sac_parser::CIFToken sac_parser::get_next_token()
|
||||
{
|
||||
std::string s = to_lower_copy(m_token_value);
|
||||
|
||||
if (s == "global_")
|
||||
result = CIFToken::GLOBAL;
|
||||
else if (s == "stop_")
|
||||
result = CIFToken::STOP;
|
||||
else if (s == "loop_")
|
||||
result = CIFToken::LOOP;
|
||||
else if (s == "data_")
|
||||
if (s == "data_")
|
||||
{
|
||||
state = State::DATA;
|
||||
continue;
|
||||
}
|
||||
else if (s == "save_")
|
||||
|
||||
if (s == "save_")
|
||||
{
|
||||
state = State::SAVE;
|
||||
continue;
|
||||
@@ -405,6 +394,12 @@ sac_parser::CIFToken sac_parser::get_next_token()
|
||||
|
||||
if (m_token_value == ".")
|
||||
mTokenType = CIFValue::Inapplicable;
|
||||
else if (iequals(m_token_value, "global_"))
|
||||
result = CIFToken::GLOBAL;
|
||||
else if (iequals(m_token_value, "stop_"))
|
||||
result = CIFToken::STOP;
|
||||
else if (iequals(m_token_value, "loop_"))
|
||||
result = CIFToken::LOOP;
|
||||
else if (m_token_value == "?")
|
||||
{
|
||||
mTokenType = CIFValue::Unknown;
|
||||
@@ -786,6 +781,9 @@ void sac_parser::parse_save_frame()
|
||||
|
||||
void parser::produce_datablock(const std::string &name)
|
||||
{
|
||||
if (VERBOSE >= 4)
|
||||
std::cerr << "producing data_" << name << std::endl;
|
||||
|
||||
const auto &[iter, ignore] = m_file.emplace(name);
|
||||
m_datablock = &(*iter);
|
||||
}
|
||||
@@ -801,7 +799,7 @@ void parser::produce_category(const std::string &name)
|
||||
|
||||
void parser::produce_row()
|
||||
{
|
||||
if (VERBOSE >= 4)
|
||||
if (VERBOSE >= 4 and m_category != nullptr)
|
||||
std::cerr << "producing row for category " << m_category->name() << std::endl;
|
||||
|
||||
if (m_category == nullptr)
|
||||
|
||||
@@ -24,6 +24,10 @@
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <cif++.hpp>
|
||||
#include <cif++/pdb/cif2pdb.hpp>
|
||||
#include <cif++/gzio.hpp>
|
||||
|
||||
#include <cmath>
|
||||
#include <deque>
|
||||
#include <iomanip>
|
||||
@@ -31,9 +35,6 @@
|
||||
#include <regex>
|
||||
#include <set>
|
||||
|
||||
#include <cif++.hpp>
|
||||
#include <cif++/pdb/cif2pdb.hpp>
|
||||
#include <cif++/gzio.hpp>
|
||||
|
||||
namespace cif::pdb
|
||||
{
|
||||
@@ -121,9 +122,9 @@ std::string cifSoftware(const datablock &db, SoftwareType sw)
|
||||
{
|
||||
switch (sw)
|
||||
{
|
||||
case eRefinement: result = db["computing"].find1<std::string>(key("entry_id") == db.name(), "structure_refinement"); break;
|
||||
case eDataScaling: result = db["computing"].find1<std::string>(key("entry_id") == db.name(), "pdbx_data_reduction_ds"); break;
|
||||
case eDataReduction: result = db["computing"].find1<std::string>(key("entry_id") == db.name(), "pdbx_data_reduction_ii"); break;
|
||||
case eRefinement: result = db["computing"].find_first<std::string>(key("entry_id") == db.name(), "structure_refinement"); break;
|
||||
case eDataScaling: result = db["computing"].find_first<std::string>(key("entry_id") == db.name(), "pdbx_data_reduction_ds"); break;
|
||||
case eDataReduction: result = db["computing"].find_first<std::string>(key("entry_id") == db.name(), "pdbx_data_reduction_ii"); break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
@@ -135,11 +136,11 @@ std::string cifSoftware(const datablock &db, SoftwareType sw)
|
||||
|
||||
switch (sw)
|
||||
{
|
||||
case eRefinement: r = software.find1(key("classification") == "refinement"); break;
|
||||
case eDataScaling: r = software.find1(key("classification") == "data scaling"); break;
|
||||
case eDataExtraction: r = software.find1(key("classification") == "data extraction"); break;
|
||||
case eDataReduction: r = software.find1(key("classification") == "data reduction"); break;
|
||||
case ePhasing: r = software.find1(key("classification") == "phasing"); break;
|
||||
case eRefinement: r = software.find_first(key("classification") == "refinement"); break;
|
||||
case eDataScaling: r = software.find_first(key("classification") == "data scaling"); break;
|
||||
case eDataExtraction: r = software.find_first(key("classification") == "data extraction"); break;
|
||||
case eDataReduction: r = software.find_first(key("classification") == "data reduction"); break;
|
||||
case ePhasing: r = software.find_first(key("classification") == "phasing"); break;
|
||||
}
|
||||
|
||||
if (not r.empty())
|
||||
@@ -671,6 +672,7 @@ class Fi : public FBase
|
||||
virtual void out(std::ostream &os)
|
||||
{
|
||||
std::string s{ text() };
|
||||
|
||||
if (s.empty())
|
||||
{
|
||||
os << "NULL";
|
||||
@@ -678,7 +680,18 @@ class Fi : public FBase
|
||||
os << std::string(os.width() - 4, ' ');
|
||||
}
|
||||
else
|
||||
os << std::stol(s);
|
||||
{
|
||||
long l = 0;
|
||||
auto r = std::from_chars(s.data(), s.data() + s.length(), l);
|
||||
if (r.ec != std::errc())
|
||||
{
|
||||
if (VERBOSE > 0)
|
||||
std::cerr << "Failed to write '" << s << "' as a long from field " << mField << ", this indicates an error in the code for writing PDB files" << std::endl;
|
||||
os << s;
|
||||
}
|
||||
else
|
||||
os << l;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -711,7 +724,7 @@ class Ff : public FBase
|
||||
if (r.ec != std::errc())
|
||||
{
|
||||
if (VERBOSE > 0)
|
||||
std::cerr << "Failed to write '" << s << "' as a double, this indicates an error in the code for writing PDB files" << std::endl;
|
||||
std::cerr << "Failed to write '" << s << "' as a double from field " << mField << ", this indicates an error in the code for writing PDB files" << std::endl;
|
||||
os << s;
|
||||
}
|
||||
else
|
||||
@@ -957,7 +970,7 @@ void WriteRemark3BusterTNT(std::ostream &pdbFile, const datablock &db)
|
||||
for (auto t : tls)
|
||||
{
|
||||
std::string id = t["id"].as<std::string>();
|
||||
auto g = db["pdbx_refine_tls_group"].find1(key("refine_tls_id") == id);
|
||||
auto g = db["pdbx_refine_tls_group"].find_first(key("refine_tls_id") == id);
|
||||
|
||||
pdbFile << RM3("") << std::endl
|
||||
<< RM3(" TLS GROUP : ") << id << std::endl
|
||||
@@ -1383,7 +1396,7 @@ void WriteRemark3Refmac(std::ostream &pdbFile, const datablock &db)
|
||||
unit = " : ";
|
||||
|
||||
pdbFile << RM3(" ", 18) << type
|
||||
<< SEP("", -2) << Fi(l, "pdbx_ens_id")
|
||||
<< SEP("", -2) << Fs(l, "pdbx_ens_id")
|
||||
<< SEP(" ", 1) << Fs(l, "pdbx_auth_asym_id")
|
||||
<< SEP(unit.c_str(), -6) << Fi(l, "pdbx_number")
|
||||
<< SEP(" ;", -6, 3) << Ff(l, "rms_dev_position")
|
||||
@@ -1655,7 +1668,7 @@ void WriteRemark3Phenix(std::ostream &pdbFile, const datablock &db)
|
||||
{
|
||||
std::string id = t["id"].as<std::string>();
|
||||
|
||||
auto pdbx_refine_tls_group = db["pdbx_refine_tls_group"].find1(key("refine_tls_id") == id);
|
||||
auto pdbx_refine_tls_group = db["pdbx_refine_tls_group"].find_first(key("refine_tls_id") == id);
|
||||
|
||||
pdbFile << RM3(" TLS GROUP : ") << id << std::endl
|
||||
<< RM3(" SELECTION: ") << Fs(pdbx_refine_tls_group, "selection_details") << std::endl
|
||||
@@ -2187,20 +2200,20 @@ void WriteRemark200(std::ostream &pdbFile, const datablock &db)
|
||||
std::string diffrn_id = diffrn["id"].as<std::string>();
|
||||
std::string crystal_id = diffrn["crystal_id"].as<std::string>();
|
||||
|
||||
auto diffrn_radiation = db["diffrn_radiation"].find1(key("diffrn_id") == diffrn_id);
|
||||
auto diffrn_radiation_wavelength = db["diffrn_radiation_wavelength"].find1(key("id") == diffrn_radiation["wavelength_id"].as<std::string>());
|
||||
auto diffrn_source = db["diffrn_source"].find1(key("diffrn_id") == diffrn_id);
|
||||
auto diffrn_detector = db["diffrn_detector"].find1(key("diffrn_id") == diffrn_id);
|
||||
auto exptl = db["exptl"].find1(key("entry_id") == db.name());
|
||||
auto exptl_crystal = db["exptl_crystal"].find1(key("id") == crystal_id);
|
||||
auto exptl_crystal_grow = db["exptl_crystal_grow"].find1(key("crystal_id") == crystal_id);
|
||||
auto computing = db["computing"].find1(key("entry_id") == db.name());
|
||||
auto reflns = db["reflns"].find1(key("entry_id") == db.name());
|
||||
auto diffrn_radiation = db["diffrn_radiation"].find_first(key("diffrn_id") == diffrn_id);
|
||||
auto diffrn_radiation_wavelength = db["diffrn_radiation_wavelength"].find_first(key("id") == diffrn_radiation["wavelength_id"].as<std::string>());
|
||||
auto diffrn_source = db["diffrn_source"].find_first(key("diffrn_id") == diffrn_id);
|
||||
auto diffrn_detector = db["diffrn_detector"].find_first(key("diffrn_id") == diffrn_id);
|
||||
auto exptl = db["exptl"].find_first(key("entry_id") == db.name());
|
||||
auto exptl_crystal = db["exptl_crystal"].find_first(key("id") == crystal_id);
|
||||
auto exptl_crystal_grow = db["exptl_crystal_grow"].find_first(key("crystal_id") == crystal_id);
|
||||
auto computing = db["computing"].find_first(key("entry_id") == db.name());
|
||||
auto reflns = db["reflns"].find_first(key("entry_id") == db.name());
|
||||
|
||||
std::string pdbx_diffrn_id = reflns["pdbx_diffrn_id"].as<std::string>();
|
||||
|
||||
auto reflns_shell = db["reflns_shell"].find1(key("pdbx_diffrn_id") == pdbx_diffrn_id);
|
||||
auto refine = db["refine"].find1(key("pdbx_diffrn_id") == pdbx_diffrn_id);
|
||||
auto reflns_shell = db["reflns_shell"].find_first(key("pdbx_diffrn_id") == pdbx_diffrn_id);
|
||||
auto refine = db["refine"].find_first(key("pdbx_diffrn_id") == pdbx_diffrn_id);
|
||||
|
||||
std::string date =
|
||||
diffrn_detector.empty() ? "NULL" : cif2pdbDate(diffrn_detector["pdbx_collection_date"].as<std::string>());
|
||||
@@ -2325,7 +2338,7 @@ void WriteRemark280(std::ostream &pdbFile, const datablock &db)
|
||||
for (auto exptl_crystal : db["exptl_crystal"])
|
||||
{
|
||||
std::string crystal_id = exptl_crystal["id"].as<std::string>();
|
||||
auto exptl_crystal_grow = db["exptl_crystal_grow"].find1(key("crystal_id") == crystal_id);
|
||||
auto exptl_crystal_grow = db["exptl_crystal_grow"].find_first(key("crystal_id") == crystal_id);
|
||||
|
||||
pdbFile
|
||||
<< RM("") << std::endl
|
||||
@@ -2457,7 +2470,7 @@ void WriteRemark350(std::ostream &pdbFile, const datablock &db)
|
||||
}
|
||||
}
|
||||
|
||||
auto gen = db["pdbx_struct_assembly_gen"].find1(key("assembly_id") == id);
|
||||
auto gen = db["pdbx_struct_assembly_gen"].find_first(key("assembly_id") == id);
|
||||
|
||||
if (gen)
|
||||
{
|
||||
@@ -2471,7 +2484,7 @@ void WriteRemark350(std::ostream &pdbFile, const datablock &db)
|
||||
|
||||
for (auto oper_id : split<std::string>(oper_id_list, ",", true))
|
||||
{
|
||||
auto r = db["pdbx_struct_oper_list"].find1(key("id") == oper_id);
|
||||
auto r = db["pdbx_struct_oper_list"].find_first(key("id") == oper_id);
|
||||
|
||||
pdbFile << RM(" BIOMT1 ", -3) << Fs(r, "id")
|
||||
<< SEP(" ", -9, 6) << Ff(r, "matrix[1][1]")
|
||||
@@ -2951,7 +2964,7 @@ int WriteHeterogen(std::ostream &pdbFile, const datablock &db)
|
||||
if (id == water_comp_id)
|
||||
continue;
|
||||
|
||||
std::string syn = db["chem_comp"].find1<std::string>(key("id") == id, "pdbx_synonyms");
|
||||
std::string syn = db["chem_comp"].find_first<std::string>(key("id") == id, "pdbx_synonyms");
|
||||
if (syn.empty())
|
||||
continue;
|
||||
|
||||
@@ -3104,7 +3117,7 @@ std::tuple<int, int> WriteSecondaryStructure(std::ostream &pdbFile, const databl
|
||||
std::string initResName, initChainID, initICode, endResName, endChainID, endICode;
|
||||
int initSeqNum, endSeqNum;
|
||||
|
||||
auto r1 = db["struct_sheet_range"].find1(key("sheet_id") == sheetID and key("id") == rangeID1);
|
||||
auto r1 = db["struct_sheet_range"].find_first(key("sheet_id") == sheetID and key("id") == rangeID1);
|
||||
|
||||
cif::tie(initResName, initICode, endResName, endICode,
|
||||
initResName, initChainID, initSeqNum, endResName, endChainID, endSeqNum) = r1.get("beg_label_comp_id", "pdbx_beg_PDB_ins_code", "end_label_comp_id",
|
||||
@@ -3119,7 +3132,7 @@ std::tuple<int, int> WriteSecondaryStructure(std::ostream &pdbFile, const databl
|
||||
std::string initResName, initChainID, initICode, endResName, endChainID, endICode, curAtom, curResName, curChainID, curICode, prevAtom, prevResName, prevChainID, prevICode;
|
||||
int initSeqNum, endSeqNum, curResSeq, prevResSeq;
|
||||
|
||||
auto r2 = db["struct_sheet_range"].find1(key("sheet_id") == sheetID and key("id") == rangeID2);
|
||||
auto r2 = db["struct_sheet_range"].find_first(key("sheet_id") == sheetID and key("id") == rangeID2);
|
||||
|
||||
cif::tie(initResName, initICode, endResName, endICode,
|
||||
initResName, initChainID, initSeqNum, endResName, endChainID, endSeqNum) = r2.get("beg_label_comp_id", "pdbx_beg_PDB_ins_code", "end_label_comp_id",
|
||||
@@ -3288,10 +3301,10 @@ int WriteMiscellaneousFeatures(std::ostream &pdbFile, const datablock &db)
|
||||
|
||||
void WriteCrystallographic(std::ostream &pdbFile, const datablock &db)
|
||||
{
|
||||
auto r = db["symmetry"].find1(key("entry_id") == db.name());
|
||||
auto r = db["symmetry"].find_first(key("entry_id") == db.name());
|
||||
std::string symmetry = r["space_group_name_H-M"].as<std::string>();
|
||||
|
||||
r = db["cell"].find1(key("entry_id") == db.name());
|
||||
r = db["cell"].find_first(key("entry_id") == db.name());
|
||||
|
||||
pdbFile << cif::format("CRYST1%9.3f%9.3f%9.3f%7.2f%7.2f%7.2f %-11.11s%4d", r["length_a"].as<double>(), r["length_b"].as<double>(), r["length_c"].as<double>(), r["angle_alpha"].as<double>(), r["angle_beta"].as<double>(), r["angle_gamma"].as<double>(), symmetry, r["Z_PDB"].as<int>()) << std::endl;
|
||||
}
|
||||
@@ -3338,10 +3351,16 @@ std::tuple<int, int> WriteCoordinatesForModel(std::ostream &pdbFile, const datab
|
||||
const std::map<std::string, std::tuple<std::string, int, std::string>> &last_resseq_for_chain_map,
|
||||
std::set<std::string> &terminatedChains, int model_nr)
|
||||
{
|
||||
using namespace cif::literals;
|
||||
|
||||
int numCoord = 0, numTer = 0;
|
||||
|
||||
auto &atom_site = db["atom_site"];
|
||||
auto &atom_site_anisotrop = db["atom_site_anisotrop"];
|
||||
auto &entity = db["entity"];
|
||||
auto &pdbx_poly_seq_scheme = db["pdbx_poly_seq_scheme"];
|
||||
auto &pdbx_nonpoly_scheme = db["pdbx_nonpoly_scheme"];
|
||||
auto &pdbx_branch_scheme = db["pdbx_branch_scheme"];
|
||||
|
||||
int serial = 1;
|
||||
auto ri = atom_site.begin();
|
||||
@@ -3358,10 +3377,21 @@ std::tuple<int, int> WriteCoordinatesForModel(std::ostream &pdbFile, const datab
|
||||
cif::tie(nextResName, nextChainID, nextICode, nextResSeq, modelNum) =
|
||||
(*ri).get("label_comp_id", "auth_asym_id", "pdbx_PDB_ins_code", "auth_seq_id", "pdbx_PDB_model_num");
|
||||
|
||||
if (modelNum.empty() == false and stol(modelNum) != model_nr)
|
||||
if (modelNum.empty() == false)
|
||||
{
|
||||
++ri;
|
||||
continue;
|
||||
int nr = 0;
|
||||
auto r = std::from_chars(modelNum.data(), modelNum.data() + modelNum.length(), nr);
|
||||
if (r.ec != std::errc())
|
||||
{
|
||||
if (VERBOSE > 0)
|
||||
std::cerr << "Model number '" << modelNum << "' is not a valid integer" << std::endl;
|
||||
}
|
||||
|
||||
if (nr != model_nr)
|
||||
{
|
||||
++ri;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (chainID.empty() == false and terminatedChains.count(chainID) == 0)
|
||||
@@ -3404,6 +3434,16 @@ std::tuple<int, int> WriteCoordinatesForModel(std::ostream &pdbFile, const datab
|
||||
r.get("id", "group_PDB", "label_atom_id", "label_alt_id", "auth_comp_id", "auth_asym_id", "auth_seq_id",
|
||||
"pdbx_PDB_ins_code", "Cartn_x", "Cartn_y", "Cartn_z", "occupancy", "B_iso_or_equiv", "type_symbol", "pdbx_formal_charge");
|
||||
|
||||
int entity_id = r.get<int>("label_entity_id");
|
||||
auto type = entity.find1<std::string>("id"_key == entity_id, "type");
|
||||
|
||||
if (type == "branched") // find the real auth_seq_num, since sugars have their auth_seq_num reused as sugar number... sigh.
|
||||
resSeq = pdbx_branch_scheme.find1<int>("asym_id"_key == r.get<std::string>("label_asym_id") and "pdb_seq_num"_key == resSeq, "auth_seq_num");
|
||||
// else if (type == "non-polymer") // same for non-polymers
|
||||
// resSeq = pdbx_nonpoly_scheme.find1<int>("asym_id"_key == r.get<std::string>("label_asym_id") and "pdb_seq_num"_key == resSeq, "auth_seq_num");
|
||||
else if (type == "polymer")
|
||||
resSeq = pdbx_poly_seq_scheme.find1<int>("asym_id"_key == r.get<std::string>("label_asym_id") and "pdb_seq_num"_key == resSeq, "auth_seq_num");
|
||||
|
||||
if (chainID.length() > 1)
|
||||
throw std::runtime_error("Chain ID " + chainID + " won't fit into a PDB file");
|
||||
|
||||
@@ -3418,7 +3458,7 @@ std::tuple<int, int> WriteCoordinatesForModel(std::ostream &pdbFile, const datab
|
||||
|
||||
++numCoord;
|
||||
|
||||
auto ai = atom_site_anisotrop.find1(key("id") == id);
|
||||
auto ai = atom_site_anisotrop.find_first(key("id") == id);
|
||||
if (not ai.empty())
|
||||
//
|
||||
// auto ai = find_if(atom_site_anisotrop.begin(), atom_site_anisotrop.end(), [id](row_handle r) -> bool { return r["id"] == id; });
|
||||
|
||||
@@ -24,17 +24,16 @@
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <cif++.hpp>
|
||||
#include <cif++/pdb/pdb2cif.hpp>
|
||||
#include <cif++/pdb/pdb2cif_remark_3.hpp>
|
||||
#include <cif++/gzio.hpp>
|
||||
|
||||
#include <iomanip>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <stack>
|
||||
|
||||
#include <cif++.hpp>
|
||||
|
||||
#include <cif++/pdb/pdb2cif.hpp>
|
||||
#include <cif++/pdb/pdb2cif_remark_3.hpp>
|
||||
#include <cif++/gzio.hpp>
|
||||
|
||||
using cif::category;
|
||||
using cif::datablock;
|
||||
using cif::iequals;
|
||||
@@ -1583,7 +1582,7 @@ void PDBFileParser::ParseTitle()
|
||||
|
||||
if (not iequals(key, "MOL_ID") and mCompounds.empty())
|
||||
{
|
||||
if (cif::VERBOSE >= 0)
|
||||
if (cif::VERBOSE > 0)
|
||||
std::cerr << "Ignoring invalid COMPND record" << std::endl;
|
||||
break;
|
||||
}
|
||||
@@ -3820,41 +3819,48 @@ void PDBFileParser::ConstructEntities()
|
||||
|
||||
for (std::string monID : monIds)
|
||||
{
|
||||
std::string authMonID, authSeqNum, authInsCode;
|
||||
std::string authMonID, authSeqNum, authInsCode{'.'};
|
||||
|
||||
if (res.mSeen)
|
||||
{
|
||||
authMonID = monID;
|
||||
authSeqNum = std::to_string(res.mSeqNum);
|
||||
if (res.mIcode != ' ' and res.mIcode != 0)
|
||||
authInsCode = std::string{ res.mIcode };
|
||||
|
||||
cat->emplace({
|
||||
{ "asym_id", asymID },
|
||||
{ "entity_id", mMolID2EntityID[chain.mMolID] },
|
||||
{ "seq_id", seqID },
|
||||
{ "mon_id", monID },
|
||||
{ "ndb_seq_num", seqID },
|
||||
{ "pdb_seq_num", res.mSeqNum },
|
||||
{ "auth_seq_num", authSeqNum },
|
||||
{ "pdb_mon_id", authMonID },
|
||||
{ "auth_mon_id", authMonID },
|
||||
{ "pdb_strand_id", std::string{ chain.mDbref.chainID } },
|
||||
{ "pdb_ins_code", authInsCode },
|
||||
{ "hetero", res.mAlts.empty() ? "n" : "y" } });
|
||||
}
|
||||
else
|
||||
{
|
||||
authMonID = res.mMonID;
|
||||
authSeqNum = std::to_string(res.mSeqNum);
|
||||
|
||||
if (res.mIcode != ' ' and res.mIcode != 0)
|
||||
authInsCode = std::string{ res.mIcode } + "A";
|
||||
else
|
||||
authInsCode = "A";
|
||||
|
||||
cat->emplace({
|
||||
{ "asym_id", asymID },
|
||||
{ "entity_id", mMolID2EntityID[chain.mMolID] },
|
||||
{ "seq_id", seqID },
|
||||
{ "mon_id", monID },
|
||||
{ "ndb_seq_num", seqID },
|
||||
{ "pdb_seq_num", res.mSeqNum },
|
||||
{ "auth_seq_num", "." },
|
||||
{ "pdb_mon_id", "." },
|
||||
{ "auth_mon_id", "." },
|
||||
{ "pdb_strand_id", std::string{ chain.mDbref.chainID } },
|
||||
{ "pdb_ins_code", authInsCode },
|
||||
{ "hetero", res.mAlts.empty() ? "n" : "y" } });
|
||||
}
|
||||
|
||||
if (authInsCode.empty())
|
||||
authInsCode = ".";
|
||||
|
||||
cat->emplace({
|
||||
{ "asym_id", asymID },
|
||||
{ "entity_id", mMolID2EntityID[chain.mMolID] },
|
||||
{ "seq_id", seqID },
|
||||
{ "mon_id", monID },
|
||||
{ "ndb_seq_num", seqID },
|
||||
{ "pdb_seq_num", res.mSeqNum },
|
||||
{ "auth_seq_num", authSeqNum },
|
||||
{ "pdb_mon_id", authMonID },
|
||||
{ "auth_mon_id", authMonID },
|
||||
{ "pdb_strand_id", std::string{ chain.mDbref.chainID } },
|
||||
{ "pdb_ins_code", authInsCode },
|
||||
{ "hetero", res.mAlts.empty() ? "n" : "y" } });
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4196,7 +4202,8 @@ void PDBFileParser::ConstructEntities()
|
||||
// done with the sugar, resume operation as before
|
||||
|
||||
std::map<char, std::string> waterChains;
|
||||
std::map<std::tuple<std::string, std::string>, int> ndbSeqNum; // for nonpoly scheme
|
||||
std::map<std::tuple<std::string, std::string>, int> ndbSeqNum; // for nonpoly scheme
|
||||
std::map<std::string,int> entityAuthSeqNum; // for nonpoly scheme too
|
||||
|
||||
for (size_t i = 0; i < mHets.size(); ++i)
|
||||
{
|
||||
@@ -4325,6 +4332,7 @@ void PDBFileParser::ConstructEntities()
|
||||
}
|
||||
|
||||
int seqNr = ++ndbSeqNum[std::make_tuple(hetID, asymID)];
|
||||
int authSeqNr = ++entityAuthSeqNum[hetID];
|
||||
|
||||
std::string iCode{ het.iCode };
|
||||
cif::trim(iCode);
|
||||
@@ -4333,13 +4341,13 @@ void PDBFileParser::ConstructEntities()
|
||||
|
||||
getCategory("pdbx_nonpoly_scheme")->emplace({
|
||||
{ "asym_id", asymID },
|
||||
{ "entity_id", mHet2EntityID[hetID] },
|
||||
{ "mon_id", hetID },
|
||||
{ "ndb_seq_num", seqNr },
|
||||
{ "pdb_seq_num", het.seqNum },
|
||||
// { "auth_seq_num", het.seqNum }, // ????
|
||||
{ "entity_id", mHet2EntityID[hetID] },
|
||||
{ "mon_id", hetID },
|
||||
{ "ndb_seq_num", seqNr },
|
||||
{ "pdb_seq_num", het.seqNum },
|
||||
{ "auth_seq_num", authSeqNr }, // Yes
|
||||
{ "pdb_mon_id", hetID },
|
||||
// { "auth_mon_id", hetID },
|
||||
{ "auth_mon_id", hetID },
|
||||
{ "pdb_strand_id", std::string{ het.chainID } },
|
||||
{ "pdb_ins_code", iCode } });
|
||||
|
||||
@@ -6102,13 +6110,6 @@ int PDBFileParser::PDBChain::AlignResToSeqRes()
|
||||
switch (tb(x, y))
|
||||
{
|
||||
case -1:
|
||||
// if (cif::VERBOSE > 0)
|
||||
// std::cerr << "A residue found in the ATOM records "
|
||||
// << "(" << ry[y].mMonID << " @ " << mDbref.chainID << ":" << ry[y].mSeqNum
|
||||
// << ((ry[y].mIcode == ' ' or ry[y].mIcode == 0) ? "" : std::string{ ry[y].mIcode }) << ")"
|
||||
// << " was not found in the SEQRES records" << std::endl;
|
||||
// --y;
|
||||
|
||||
throw std::runtime_error("A residue found in the ATOM records (" + ry[y].mMonID +
|
||||
" @ " + std::string{ mDbref.chainID } + ":" + std::to_string(ry[y].mSeqNum) +
|
||||
((ry[y].mIcode == ' ' or ry[y].mIcode == 0) ? "" : std::string{ ry[y].mIcode }) +
|
||||
@@ -6123,10 +6124,11 @@ int PDBFileParser::PDBChain::AlignResToSeqRes()
|
||||
break;
|
||||
|
||||
case 0:
|
||||
if (cif::VERBOSE > 3 and rx[x].mMonID != ry[y].mMonID)
|
||||
std::cerr << "Warning, unaligned residues at " << x << "/" << y << "(" << rx[x].mMonID << '/' << ry[y].mMonID << ')' << std::endl;
|
||||
else if (cif::VERBOSE > 4)
|
||||
std::cerr << rx[x].mMonID << " -> " << ry[y].mMonID << " (" << ry[y].mSeqNum << ')' << std::endl;
|
||||
if (rx[x].mMonID != ry[y].mMonID)
|
||||
{
|
||||
std::cerr << "Warning, unaligned residues at " << x << "/" << y << "(" << rx[x].mMonID << '/' << ry[y].mMonID << ") SEQRES does not agree with ATOM records" << std::endl;
|
||||
rx[x].mMonID = ry[y].mMonID;
|
||||
}
|
||||
|
||||
rx[x].mSeqNum = ry[y].mSeqNum;
|
||||
rx[x].mIcode = ry[y].mIcode;
|
||||
@@ -6246,4 +6248,4 @@ file read(const std::filesystem::path &file)
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace pdbx
|
||||
} // namespace pdbx
|
||||
|
||||
@@ -25,12 +25,11 @@
|
||||
*/
|
||||
|
||||
#include <cif++.hpp>
|
||||
#include <cif++/pdb/pdb2cif_remark_3.hpp>
|
||||
|
||||
#include <map>
|
||||
#include <set>
|
||||
|
||||
#include <cif++/pdb/pdb2cif_remark_3.hpp>
|
||||
|
||||
namespace cif::pdb
|
||||
{
|
||||
|
||||
|
||||
@@ -27,12 +27,12 @@
|
||||
// #include <sys/ioctl.h>
|
||||
// #include <termios.h>
|
||||
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
|
||||
#include <cif++.hpp>
|
||||
#include <cif++/pdb/tls.hpp>
|
||||
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
|
||||
namespace cif
|
||||
{
|
||||
|
||||
|
||||
@@ -24,11 +24,11 @@
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <cif++/point.hpp>
|
||||
|
||||
#include <cassert>
|
||||
#include <random>
|
||||
|
||||
#include <cif++/point.hpp>
|
||||
|
||||
namespace cif
|
||||
{
|
||||
|
||||
@@ -87,17 +87,17 @@ class Matrix : public MatrixExpression<Matrix>
|
||||
Matrix &operator=(Matrix &&m) = default;
|
||||
Matrix &operator=(const Matrix &m) = default;
|
||||
|
||||
uint32_t dim_m() const { return m_m; }
|
||||
uint32_t dim_n() const { return m_n; }
|
||||
size_t dim_m() const { return m_m; }
|
||||
size_t dim_n() const { return m_n; }
|
||||
|
||||
double operator()(uint32_t i, uint32_t j) const
|
||||
double operator()(size_t i, size_t j) const
|
||||
{
|
||||
assert(i < m_m);
|
||||
assert(j < m_n);
|
||||
return m_data[i * m_n + j];
|
||||
}
|
||||
|
||||
double &operator()(uint32_t i, uint32_t j)
|
||||
double &operator()(size_t i, size_t j)
|
||||
{
|
||||
assert(i < m_m);
|
||||
assert(j < m_n);
|
||||
@@ -105,7 +105,7 @@ class Matrix : public MatrixExpression<Matrix>
|
||||
}
|
||||
|
||||
private:
|
||||
uint32_t m_m = 0, m_n = 0;
|
||||
size_t m_m = 0, m_n = 0;
|
||||
std::vector<double> m_data;
|
||||
};
|
||||
|
||||
@@ -355,6 +355,44 @@ point center_points(std::vector<point> &Points)
|
||||
return t;
|
||||
}
|
||||
|
||||
quaternion construct_for_dihedral_angle(point p1, point p2, point p3, point p4,
|
||||
float angle, float esd)
|
||||
{
|
||||
p1 -= p3;
|
||||
p2 -= p3;
|
||||
p4 -= p3;
|
||||
p3 -= p3;
|
||||
|
||||
quaternion q;
|
||||
auto axis = p2;
|
||||
|
||||
float dh = dihedral_angle(p1, p2, p3, p4);
|
||||
for (int iteration = 0; iteration < 100; ++iteration)
|
||||
{
|
||||
float delta = std::fmod(angle - dh, 360.0f);
|
||||
|
||||
if (delta < -180)
|
||||
delta += 360;
|
||||
if (delta > 180)
|
||||
delta -= 360;
|
||||
|
||||
if (std::abs(delta) < esd)
|
||||
break;
|
||||
|
||||
// if (iteration > 0)
|
||||
// std::cout << cif::coloured(("iteration " + std::to_string(iteration)).c_str(), cif::scBLUE, cif::scBLACK) << " delta: " << delta << std::endl;
|
||||
|
||||
auto q2 = construct_from_angle_axis(delta, axis);
|
||||
q = iteration == 0 ? q2 : q * q2;
|
||||
|
||||
p4.rotate(q2);
|
||||
|
||||
dh = dihedral_angle(p1, p2, p3, p4);
|
||||
}
|
||||
|
||||
return q;
|
||||
}
|
||||
|
||||
point centroid(const std::vector<point> &pts)
|
||||
{
|
||||
point result;
|
||||
@@ -522,15 +560,17 @@ quaternion align_points(const std::vector<point> &pa, const std::vector<point> &
|
||||
|
||||
point nudge(point p, float offset)
|
||||
{
|
||||
static const float kPI_f = static_cast<float>(kPI);
|
||||
|
||||
static std::random_device rd;
|
||||
static std::mt19937_64 rng(rd());
|
||||
|
||||
std::uniform_real_distribution<float> randomAngle(0, 2 * kPI);
|
||||
std::normal_distribution<> randomOffset(0, offset);
|
||||
std::uniform_real_distribution<float> randomAngle(0, 2 * kPI_f);
|
||||
std::normal_distribution<float> randomOffset(0, offset);
|
||||
|
||||
float theta = randomAngle(rng);
|
||||
float phi1 = randomAngle(rng) - kPI;
|
||||
float phi2 = randomAngle(rng) - kPI;
|
||||
float phi1 = randomAngle(rng) - kPI_f;
|
||||
float phi2 = randomAngle(rng) - kPI_f;
|
||||
|
||||
quaternion q = spherical(1.0f, theta, phi1, phi2);
|
||||
|
||||
|
||||
@@ -24,10 +24,10 @@
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
#include <cif++/symmetry.hpp>
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
#include "./symop_table_data.hpp"
|
||||
|
||||
namespace cif
|
||||
|
||||
@@ -24,11 +24,11 @@
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <cif++/text.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
|
||||
#include <cif++/text.hpp>
|
||||
|
||||
namespace cif
|
||||
{
|
||||
|
||||
|
||||
@@ -24,6 +24,9 @@
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <cif++/utilities.hpp>
|
||||
#include "revision.hpp"
|
||||
|
||||
#include <atomic>
|
||||
#include <cassert>
|
||||
#include <cmath>
|
||||
@@ -44,10 +47,6 @@
|
||||
#include <termios.h>
|
||||
#endif
|
||||
|
||||
#include <cif++/utilities.hpp>
|
||||
|
||||
#include "revision.hpp"
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
@@ -124,7 +123,8 @@ std::string get_executable_path()
|
||||
{
|
||||
using namespace std::literals;
|
||||
|
||||
char path[PATH_MAX] = "";
|
||||
// This used to be PATH_MAX, but lets simply assume 1024 is enough...
|
||||
char path[1024] = "";
|
||||
if (readlink("/proc/self/exe", path, sizeof(path)) == -1)
|
||||
throw std::runtime_error("could not get exe path "s + strerror(errno));
|
||||
return {path};
|
||||
@@ -170,13 +170,15 @@ struct ProgressImpl
|
||||
|
||||
void ProgressImpl::Run()
|
||||
{
|
||||
using namespace std::literals;
|
||||
|
||||
bool printedAny = false;
|
||||
|
||||
try
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
std::this_thread::sleep_for(2s);
|
||||
|
||||
std::unique_lock lock(mMutex);
|
||||
|
||||
@@ -405,9 +407,9 @@ struct rsrc_imp
|
||||
|
||||
#if _MSC_VER
|
||||
|
||||
extern "C" const mrsrc::rsrc_imp *gResourceIndexDefault[1] = {};
|
||||
extern "C" const char *gResourceDataDefault[1] = {};
|
||||
extern "C" const char *gResourceNameDefault[1] = {};
|
||||
extern "C" CIFPP_EXPORT const mrsrc::rsrc_imp *gResourceIndexDefault[1] = {};
|
||||
extern "C" CIFPP_EXPORT const char *gResourceDataDefault[1] = {};
|
||||
extern "C" CIFPP_EXPORT const char *gResourceNameDefault[1] = {};
|
||||
|
||||
extern "C" const mrsrc::rsrc_imp gResourceIndex[];
|
||||
extern "C" const char gResourceData[];
|
||||
|
||||
@@ -24,6 +24,11 @@
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <cif++/dictionary_parser.hpp>
|
||||
#include <cif++/validate.hpp>
|
||||
#include <cif++/utilities.hpp>
|
||||
#include <cif++/gzio.hpp>
|
||||
|
||||
#include <cassert>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
@@ -41,12 +46,6 @@ using boost::regex;
|
||||
using std::regex;
|
||||
#endif
|
||||
|
||||
#include <cif++/dictionary_parser.hpp>
|
||||
#include <cif++/validate.hpp>
|
||||
|
||||
#include <cif++/utilities.hpp>
|
||||
#include <cif++/gzio.hpp>
|
||||
|
||||
namespace cif
|
||||
{
|
||||
|
||||
|
||||
@@ -58,6 +58,12 @@ bool init_unit_test()
|
||||
// not a test, just initialize test dir
|
||||
if (boost::unit_test::framework::master_test_suite().argc == 2)
|
||||
gTestDir = boost::unit_test::framework::master_test_suite().argv[1];
|
||||
else
|
||||
{
|
||||
while (not gTestDir.empty() and not std::filesystem::exists(gTestDir / "test"))
|
||||
gTestDir = gTestDir.parent_path();
|
||||
gTestDir /= "test";
|
||||
}
|
||||
|
||||
// do this now, avoids the need for installing
|
||||
cif::add_file_resource("mmcif_pdbx.dic", gTestDir / ".." / "rsrc" / "mmcif_pdbx.dic");
|
||||
|
||||
@@ -39,6 +39,12 @@ int main(int argc, char* argv[])
|
||||
|
||||
if (argc == 3)
|
||||
testdir = argv[2];
|
||||
else
|
||||
{
|
||||
while (not testdir.empty() and not std::filesystem::exists(testdir / "test"))
|
||||
testdir = testdir.parent_path();
|
||||
testdir /= "test";
|
||||
}
|
||||
|
||||
if (std::filesystem::exists(testdir / ".." / "data" / "ccd-subset.cif"))
|
||||
cif::add_file_resource("components.cif", testdir / ".." / "data" / "ccd-subset.cif");
|
||||
|
||||
@@ -96,87 +96,87 @@ BOOST_AUTO_TEST_CASE(sugar_name_1)
|
||||
}
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// // --------------------------------------------------------------------
|
||||
|
||||
BOOST_AUTO_TEST_CASE(create_sugar_1)
|
||||
{
|
||||
using namespace cif::literals;
|
||||
// BOOST_AUTO_TEST_CASE(create_sugar_1)
|
||||
// {
|
||||
// using namespace cif::literals;
|
||||
|
||||
const std::filesystem::path example(gTestDir / "1juh.cif.gz");
|
||||
cif::file file(example.string());
|
||||
cif::mm::structure s(file);
|
||||
// const std::filesystem::path example(gTestDir / "1juh.cif.gz");
|
||||
// cif::file file(example.string());
|
||||
// cif::mm::structure s(file);
|
||||
|
||||
// collect atoms from asym L first
|
||||
auto &NAG = s.get_residue("L");
|
||||
auto nagAtoms = NAG.atoms();
|
||||
// // collect atoms from asym L first
|
||||
// auto &NAG = s.get_residue("L");
|
||||
// auto nagAtoms = NAG.atoms();
|
||||
|
||||
std::vector<cif::row_initializer> ai;
|
||||
// std::vector<cif::row_initializer> ai;
|
||||
|
||||
auto &db = s.get_datablock();
|
||||
auto &as = db["atom_site"];
|
||||
// auto &db = s.get_datablock();
|
||||
// auto &as = db["atom_site"];
|
||||
|
||||
// NOTE, row_initializer does not actually hold the data, so copy it first
|
||||
// before it gets destroyed by remove_residue
|
||||
// // NOTE, row_initializer does not actually hold the data, so copy it first
|
||||
// // before it gets destroyed by remove_residue
|
||||
|
||||
for (auto r : as.find("label_asym_id"_key == "L"))
|
||||
/*auto &ri = */ai.emplace_back(r);
|
||||
// for (auto r : as.find("label_asym_id"_key == "L"))
|
||||
// /*auto &ri = */ai.emplace_back(r);
|
||||
|
||||
s.remove_residue(NAG);
|
||||
// s.remove_residue(NAG);
|
||||
|
||||
auto &branch = s.create_branch(ai);
|
||||
// auto &branch = s.create_branch(ai);
|
||||
|
||||
BOOST_CHECK_EQUAL(branch.name(), "2-acetamido-2-deoxy-beta-D-glucopyranose");
|
||||
BOOST_CHECK_EQUAL(branch.size(), 1);
|
||||
// BOOST_CHECK_EQUAL(branch.name(), "2-acetamido-2-deoxy-beta-D-glucopyranose");
|
||||
// BOOST_CHECK_EQUAL(branch.size(), 1);
|
||||
|
||||
BOOST_CHECK_EQUAL(branch[0].atoms().size(), nagAtoms.size());
|
||||
// BOOST_CHECK_EQUAL(branch[0].atoms().size(), nagAtoms.size());
|
||||
|
||||
BOOST_CHECK(file.is_valid());
|
||||
// BOOST_CHECK(file.is_valid());
|
||||
|
||||
file.save(gTestDir / "test-create_sugar_1.cif");
|
||||
}
|
||||
// file.save(gTestDir / "test-create_sugar_1.cif");
|
||||
// }
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// // --------------------------------------------------------------------
|
||||
|
||||
BOOST_AUTO_TEST_CASE(create_sugar_2)
|
||||
{
|
||||
using namespace cif::literals;
|
||||
// BOOST_AUTO_TEST_CASE(create_sugar_2)
|
||||
// {
|
||||
// using namespace cif::literals;
|
||||
|
||||
const std::filesystem::path example(gTestDir / "1juh.cif.gz");
|
||||
cif::file file(example.string());
|
||||
cif::mm::structure s(file);
|
||||
// const std::filesystem::path example(gTestDir / "1juh.cif.gz");
|
||||
// cif::file file(example.string());
|
||||
// cif::mm::structure s(file);
|
||||
|
||||
// Get branch for H
|
||||
auto &bH = s.get_branch_by_asym_id("H");
|
||||
// // Get branch for H
|
||||
// auto &bH = s.get_branch_by_asym_id("H");
|
||||
|
||||
BOOST_CHECK_EQUAL(bH.size(), 2);
|
||||
// BOOST_CHECK_EQUAL(bH.size(), 2);
|
||||
|
||||
std::vector<cif::row_initializer> ai[2];
|
||||
// std::vector<cif::row_initializer> ai[2];
|
||||
|
||||
auto &db = s.get_datablock();
|
||||
auto &as = db["atom_site"];
|
||||
// auto &db = s.get_datablock();
|
||||
// auto &as = db["atom_site"];
|
||||
|
||||
for (size_t i = 0; i < 2; ++i)
|
||||
{
|
||||
for (auto r : as.find("label_asym_id"_key == "H" and "auth_seq_id"_key == i + 1))
|
||||
/*auto &ri = */ai[i].emplace_back(r);
|
||||
}
|
||||
// for (size_t i = 0; i < 2; ++i)
|
||||
// {
|
||||
// for (auto r : as.find("label_asym_id"_key == "H" and "auth_seq_id"_key == i + 1))
|
||||
// /*auto &ri = */ai[i].emplace_back(r);
|
||||
// }
|
||||
|
||||
s.remove_branch(bH);
|
||||
// s.remove_branch(bH);
|
||||
|
||||
BOOST_CHECK(file.is_valid());
|
||||
// BOOST_CHECK(file.is_valid());
|
||||
|
||||
auto &bN = s.create_branch(ai[0]);
|
||||
s.extend_branch(bN.get_asym_id(), ai[1], 1, "O4");
|
||||
// auto &bN = s.create_branch(ai[0]);
|
||||
// s.extend_branch(bN.get_asym_id(), ai[1], 1, "O4");
|
||||
|
||||
BOOST_CHECK_EQUAL(bN.name(), "2-acetamido-2-deoxy-beta-D-glucopyranose-(1-4)-2-acetamido-2-deoxy-beta-D-glucopyranose");
|
||||
BOOST_CHECK_EQUAL(bN.size(), 2);
|
||||
// BOOST_CHECK_EQUAL(bN.name(), "2-acetamido-2-deoxy-beta-D-glucopyranose-(1-4)-2-acetamido-2-deoxy-beta-D-glucopyranose");
|
||||
// BOOST_CHECK_EQUAL(bN.size(), 2);
|
||||
|
||||
BOOST_CHECK(file.is_valid());
|
||||
// BOOST_CHECK(file.is_valid());
|
||||
|
||||
file.save(gTestDir / "test-create_sugar_2.cif");
|
||||
// file.save(gTestDir / "test-create_sugar_2.cif");
|
||||
|
||||
BOOST_CHECK_NO_THROW(cif::mm::structure s2(file));
|
||||
}
|
||||
// BOOST_CHECK_NO_THROW(cif::mm::structure s2(file));
|
||||
// }
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
|
||||
@@ -87,19 +87,20 @@ BOOST_AUTO_TEST_CASE(t1)
|
||||
// q = Normalize(q);
|
||||
|
||||
// Quaternion q{ 0.1, 0.2, 0.3, 0.4 };
|
||||
cif::quaternion q{0.5, 0.5, 0.5, 0.5};
|
||||
cif::quaternion q{ 0.5, 0.5, 0.5, 0.5 };
|
||||
q = normalize(q);
|
||||
|
||||
const auto &&[angle0, axis0] = cif::quaternion_to_angle_axis(q);
|
||||
|
||||
std::vector<cif::point> p1{
|
||||
{16.979, 13.301, 44.555},
|
||||
{18.150, 13.525, 43.680},
|
||||
{18.656, 14.966, 43.784},
|
||||
{17.890, 15.889, 44.078},
|
||||
{17.678, 13.270, 42.255},
|
||||
{16.248, 13.734, 42.347},
|
||||
{15.762, 13.216, 43.724}};
|
||||
{ 16.979f, 13.301f, 44.555f },
|
||||
{ 18.150f, 13.525f, 43.680f },
|
||||
{ 18.656f, 14.966f, 43.784f },
|
||||
{ 17.890f, 15.889f, 44.078f },
|
||||
{ 17.678f, 13.270f, 42.255f },
|
||||
{ 16.248f, 13.734f, 42.347f },
|
||||
{ 15.762f, 13.216f, 43.724f }
|
||||
};
|
||||
|
||||
auto p2 = p1;
|
||||
|
||||
@@ -119,7 +120,7 @@ BOOST_AUTO_TEST_CASE(t1)
|
||||
for (auto &p : p1)
|
||||
p.rotate(q2);
|
||||
|
||||
float rmsd = cif::RMSd(p1, p2);
|
||||
auto rmsd = cif::RMSd(p1, p2);
|
||||
|
||||
BOOST_TEST(rmsd < 1e-5);
|
||||
|
||||
@@ -136,7 +137,7 @@ BOOST_AUTO_TEST_CASE(t2)
|
||||
|
||||
cif::point xp = cif::cross_product(p[1] - p[0], p[2] - p[0]);
|
||||
|
||||
auto q = cif::construct_from_angle_axis(45, xp); //mmcif::Normalize(Quaternion{45 * mmcif::kPI / 180, xp.mX, xp.mY, xp.mZ});
|
||||
auto q = cif::construct_from_angle_axis(45, xp); // mmcif::Normalize(Quaternion{45 * mmcif::kPI / 180, xp.mX, xp.mY, xp.mZ});
|
||||
|
||||
auto &&[angle, axis] = cif::quaternion_to_angle_axis(q);
|
||||
|
||||
@@ -153,7 +154,7 @@ BOOST_AUTO_TEST_CASE(t3)
|
||||
|
||||
cif::point xp = cif::cross_product(p[1] - p[0], p[2] - p[0]);
|
||||
|
||||
auto q = cif::construct_from_angle_axis(45, xp); //mmcif::Normalize(Quaternion{45 * mmcif::kPI / 180, xp.mX, xp.mY, xp.mZ});
|
||||
auto q = cif::construct_from_angle_axis(45, xp); // mmcif::Normalize(Quaternion{45 * mmcif::kPI / 180, xp.mX, xp.mY, xp.mZ});
|
||||
|
||||
auto v = p[1];
|
||||
v -= p[0];
|
||||
@@ -166,3 +167,48 @@ BOOST_AUTO_TEST_CASE(t3)
|
||||
|
||||
BOOST_TEST(a == 45, tt::tolerance(0.01));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(dh_q_1)
|
||||
{
|
||||
struct
|
||||
{
|
||||
float angle;
|
||||
cif::point pts[4];
|
||||
} tests[] = {
|
||||
{ -97.5f,
|
||||
{ { 68.8649979f, -7.34800005f, 54.3769989f },
|
||||
{ 68.1350021f, -8.18700027f, 53.6489983f },
|
||||
{ 68.7760239f, -9.07335377f, 52.7140236f },
|
||||
{ 68.9000015f, -10.3944235f, 53.2217026f } } },
|
||||
{ 80.3f,
|
||||
{ { 0.304512024f, 0.531184196f, 2.25860214f },
|
||||
{ 0.956512451f, 0.0321846008f, 1.07460022f },
|
||||
{ 0, 0, 0 },
|
||||
{ 0.21336633f, -1.09552193f, -0.878999829f } } },
|
||||
{ -97.5f,
|
||||
{ { 0.088973999f, 1.72535372f, 1.66297531f },
|
||||
{ -0.641021729f, 0.886353493f, 0.93497467f },
|
||||
{ 0, 0, 0 },
|
||||
{ 1.29433727f, -0.395142615f, 0.432300746f } } },
|
||||
{ -97.5f,
|
||||
{
|
||||
{ 0.088973999f, 1.72535372f, 1.66297531f },
|
||||
{ -0.641021729f, 0.886353493f, 0.93497467f },
|
||||
{ 0, 0, 0 },
|
||||
{ 1.33983064f, 0.384027064f, -0.275154471f },
|
||||
|
||||
} }
|
||||
};
|
||||
|
||||
for (auto &&[angle, pts] : tests)
|
||||
{
|
||||
auto q = cif::construct_for_dihedral_angle(pts[0], pts[1], pts[2], pts[3], angle, 1);
|
||||
|
||||
pts[3] -= pts[2];
|
||||
pts[3].rotate(q);
|
||||
pts[3] += pts[2];
|
||||
|
||||
auto dh = cif::dihedral_angle(pts[0], pts[1], pts[2], pts[3]);
|
||||
BOOST_TEST(dh == angle, tt::tolerance(0.1f));
|
||||
}
|
||||
}
|
||||
@@ -78,23 +78,23 @@ bool init_unit_test()
|
||||
BOOST_AUTO_TEST_CASE(cc_1)
|
||||
{
|
||||
std::tuple<std::string_view, float, char> tests[] = {
|
||||
{ "1.0", 1.0, 0 },
|
||||
{ "1.0e10", 1.0e10, 0 },
|
||||
{ "-1.1e10", -1.1e10, 0 },
|
||||
{ "-.2e11", -.2e11, 0 },
|
||||
{ "1.3e-10", 1.3e-10, 0 },
|
||||
{ "1.0", 1.0f, 0 },
|
||||
{ "1.0e10", 1.0e10f, 0 },
|
||||
{ "-1.1e10", -1.1e10f, 0 },
|
||||
{ "-.2e11", -.2e11f, 0 },
|
||||
{ "1.3e-10", 1.3e-10f, 0 },
|
||||
|
||||
{ "1.0 ", 1.0, ' ' },
|
||||
{ "1.0e10 ", 1.0e10, ' ' },
|
||||
{ "-1.1e10 ", -1.1e10, ' ' },
|
||||
{ "-.2e11 ", -.2e11, ' ' },
|
||||
{ "1.3e-10 ", 1.3e-10, ' ' },
|
||||
{ "1.0 ", 1.0f, ' ' },
|
||||
{ "1.0e10 ", 1.0e10f, ' ' },
|
||||
{ "-1.1e10 ", -1.1e10f, ' ' },
|
||||
{ "-.2e11 ", -.2e11f, ' ' },
|
||||
{ "1.3e-10 ", 1.3e-10f, ' ' },
|
||||
|
||||
{ "3.0", 3.0, 0 },
|
||||
{ "3.0 ", 3.0, ' ' },
|
||||
{ "3.0", 3.0f, 0 },
|
||||
{ "3.0 ", 3.0f, ' ' },
|
||||
|
||||
{ "3.000000", 3.0, 0 },
|
||||
{ "3.000000 ", 3.0, ' ' },
|
||||
{ "3.000000", 3.0f, 0 },
|
||||
{ "3.000000 ", 3.0f, ' ' },
|
||||
};
|
||||
|
||||
for (const auto &[txt, val, ch] : tests)
|
||||
@@ -112,7 +112,7 @@ BOOST_AUTO_TEST_CASE(cc_1)
|
||||
BOOST_AUTO_TEST_CASE(cc_2)
|
||||
{
|
||||
std::tuple<float, int, std::string_view> tests[] = {
|
||||
{ 1.1, 1, "1.1" }
|
||||
{ 1.1f, 1, "1.1" }
|
||||
};
|
||||
|
||||
for (const auto &[val, prec, test] : tests)
|
||||
@@ -131,7 +131,7 @@ BOOST_AUTO_TEST_CASE(item_1)
|
||||
using namespace cif;
|
||||
|
||||
item i1("1", "1");
|
||||
item i2("2", 2.0);
|
||||
item i2("2", 2.0f);
|
||||
item i3("3", '3');
|
||||
|
||||
item ci1(i1);
|
||||
@@ -163,23 +163,23 @@ BOOST_AUTO_TEST_CASE(r_1)
|
||||
c.emplace({
|
||||
{ "f-1", 1 },
|
||||
{ "f-2", "two" },
|
||||
{ "f-3", 3.0, 3 },
|
||||
{ "f-3", 3.0f, 3 },
|
||||
});
|
||||
|
||||
auto row = c.front();
|
||||
BOOST_CHECK_EQUAL(row["f-1"].compare(1), 0);
|
||||
BOOST_CHECK_EQUAL(row["f-2"].compare("two"), 0);
|
||||
BOOST_CHECK_EQUAL(row["f-3"].compare(3.0), 0); // This fails when running in valgrind... sigh
|
||||
BOOST_CHECK_EQUAL(row["f-3"].compare(3.0f), 0); // This fails when running in valgrind... sigh
|
||||
|
||||
const auto &[f1, f2, f3] = row.get<int, std::string, float>("f-1", "f-2", "f-3");
|
||||
|
||||
BOOST_CHECK_EQUAL(f1, 1);
|
||||
BOOST_CHECK_EQUAL(f2, "two");
|
||||
BOOST_CHECK_EQUAL(f3, 3.0); // This fails when running in valgrind... sigh
|
||||
BOOST_CHECK_EQUAL(f3, 3.0f); // This fails when running in valgrind... sigh
|
||||
|
||||
BOOST_CHECK_EQUAL(row.get<int>("f-1"), 1);
|
||||
BOOST_CHECK_EQUAL(row.get<std::string>("f-2"), "two");
|
||||
BOOST_CHECK_EQUAL(row.get<float>("f-3"), 3.0);
|
||||
BOOST_CHECK_EQUAL(row.get<float>("f-3"), 3.0f);
|
||||
|
||||
int f_1;
|
||||
std::string f_2;
|
||||
@@ -189,7 +189,7 @@ BOOST_AUTO_TEST_CASE(r_1)
|
||||
|
||||
BOOST_CHECK_EQUAL(f_1, 1);
|
||||
BOOST_CHECK_EQUAL(f_2, "two");
|
||||
BOOST_CHECK_EQUAL(f_3, 3.0); // This fails when running in valgrind... sigh
|
||||
BOOST_CHECK_EQUAL(f_3, 3.0f); // This fails when running in valgrind... sigh
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(r_2)
|
||||
@@ -486,14 +486,14 @@ _test.value
|
||||
BOOST_CHECK_EQUAL(++n, 1);
|
||||
BOOST_CHECK_EQUAL(r["id"].as<int>(), 1);
|
||||
BOOST_CHECK_EQUAL(r["name"].as<std::string>(), "aap");
|
||||
BOOST_CHECK_EQUAL(r["value"].as<float>(), 1.0);
|
||||
BOOST_CHECK_EQUAL(r["value"].as<float>(), 1.0f);
|
||||
}
|
||||
|
||||
auto t = test.find(cif::key("id") == 1);
|
||||
BOOST_CHECK(not t.empty());
|
||||
BOOST_CHECK_EQUAL(t.front()["name"].as<std::string>(), "aap");
|
||||
|
||||
auto t2 = test.find(cif::key("value") == 1.2);
|
||||
auto t2 = test.find(cif::key("value") == 1.2f);
|
||||
BOOST_CHECK(not t2.empty());
|
||||
BOOST_CHECK_EQUAL(t2.front()["name"].as<std::string>(), "mies");
|
||||
}
|
||||
@@ -1774,8 +1774,6 @@ _test.name
|
||||
|
||||
BOOST_AUTO_TEST_CASE(c3)
|
||||
{
|
||||
cif::VERBOSE = 1;
|
||||
|
||||
auto f = R"(data_TEST
|
||||
#
|
||||
loop_
|
||||
@@ -1811,6 +1809,43 @@ _test.name
|
||||
BOOST_CHECK_EQUAL(name, "aap");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(c4)
|
||||
{
|
||||
auto f = R"(data_TEST
|
||||
#
|
||||
loop_
|
||||
_test.id
|
||||
_test.name
|
||||
1 aap
|
||||
2 noot
|
||||
3 mies
|
||||
4 .
|
||||
5 ?
|
||||
)"_cf;
|
||||
|
||||
auto &db = f.front();
|
||||
|
||||
// query tests
|
||||
BOOST_TEST(db["test"].find_max<int>("id") == 5);
|
||||
BOOST_TEST(db["test"].find_max<int>("id", cif::key("name") != cif::null) == 3);
|
||||
|
||||
BOOST_TEST(db["test"].find_min<int>("id") == 1);
|
||||
BOOST_TEST(db["test"].find_min<int>("id", cif::key("name") == cif::null) == 4);
|
||||
|
||||
// count tests
|
||||
BOOST_TEST(db["test"].count(cif::all()) == 5);
|
||||
BOOST_TEST(db["test"].count(cif::key("name") != cif::null) == 3);
|
||||
BOOST_TEST(db["test"].count(cif::key("name") == cif::null) == 2);
|
||||
|
||||
// find_first tests
|
||||
BOOST_TEST(db["test"].find_first<int>(cif::key("id") == 1, "id") == 1);
|
||||
BOOST_TEST(db["test"].find_first<int>(cif::all(), "id") == 1);
|
||||
|
||||
// find1 tests
|
||||
BOOST_TEST(db["test"].find1<int>(cif::key("id") == 1, "id") == 1);
|
||||
BOOST_CHECK_THROW(db["test"].find1<int>(cif::all(), "id"), cif::multiple_results_error);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// rename test
|
||||
|
||||
@@ -2322,15 +2357,22 @@ _test.text ??
|
||||
|
||||
BOOST_AUTO_TEST_CASE(output_test_1)
|
||||
{
|
||||
cif::VERBOSE = 5;
|
||||
|
||||
auto data1 = R"(
|
||||
data_Q
|
||||
loop_
|
||||
_test.text
|
||||
"stop_the_crap"
|
||||
stop_the_crap
|
||||
'and stop_ this too'
|
||||
'data_dinges'
|
||||
'blablaglobal_bla'
|
||||
blablaglobal_bla
|
||||
boo.data_.whatever
|
||||
'data_.whatever'
|
||||
'stop_'
|
||||
'loop_'
|
||||
'global_'
|
||||
'_with.leading_underscore'
|
||||
)"_cf;
|
||||
|
||||
auto &db1 = data1.front();
|
||||
@@ -2341,11 +2383,16 @@ boo.data_.whatever
|
||||
const char *s;
|
||||
bool q;
|
||||
} kS[] = {
|
||||
{ "stop_the_crap", false },
|
||||
{ "stop_the_crap", true },
|
||||
{ "and stop_ this too", false },
|
||||
{ "data_dinges", false },
|
||||
{ "blablaglobal_bla", false },
|
||||
{ "boo.data_.whatever", true }
|
||||
{ "blablaglobal_bla", true },
|
||||
{ "boo.data_.whatever", true },
|
||||
{ "data_.whatever", false },
|
||||
{ "stop_", false },
|
||||
{ "loop_", false },
|
||||
{ "global_", false },
|
||||
{ "_with.leading_underscore", false }
|
||||
};
|
||||
|
||||
BOOST_CHECK_EQUAL(test1.size(), sizeof(kS) / sizeof(T));
|
||||
|
||||
@@ -1,55 +1,71 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Code updated based on a bug report in Ubuntu:
|
||||
# Bug #1999259 reported by Kyler Laird on 2022-12-09
|
||||
|
||||
set -e
|
||||
|
||||
if [ "$EUID" -ne 0 ]
|
||||
then echo "Please run as root"
|
||||
# Get the effective UID, but do so in a compatible way (we may be running dash)
|
||||
euid=${EUID:-$(id -u)}
|
||||
|
||||
if [ "${euid}" -ne 0 ]; then
|
||||
echo "Please run as root"
|
||||
exit
|
||||
fi
|
||||
|
||||
if [ -f "@CIFPP_ETC_DIR@/libcifpp.conf" ] ; then
|
||||
if [ -f "@CIFPP_ETC_DIR@/libcifpp.conf" ]; then
|
||||
. "@CIFPP_ETC_DIR@/libcifpp.conf"
|
||||
fi
|
||||
|
||||
# check to see if we're supposed to run at all
|
||||
if [ "$update" != "true" ] ; then
|
||||
if [ "$update" != "true" ]; then
|
||||
exit
|
||||
fi
|
||||
|
||||
# if cache directory doesn't exist, exit.
|
||||
# if cache directory doesn't exist, exit.
|
||||
if ! [ -d "@CIFPP_CACHE_DIR@" ]; then
|
||||
exit
|
||||
fi
|
||||
|
||||
fetch_dictionary () {
|
||||
# Create a temp file in the right directory and
|
||||
# make sure it is cleaned up when this script exits
|
||||
|
||||
tmpfile=$(mktemp)
|
||||
trap "rm -f \"${tmpfile}\"" EXIT
|
||||
|
||||
update_dictionary() {
|
||||
dict=$1
|
||||
source=$2
|
||||
|
||||
wget -O${dict}.gz ${source}
|
||||
# Using curl with
|
||||
# --location (follow redirects)
|
||||
# --silent (no diagnostic output at all)
|
||||
# --time-cond (only fetch if source is newer)
|
||||
#
|
||||
# Output is extracted and written to $tmpfile and when successful
|
||||
# the tmpfile is placed at the desired location and updated is set
|
||||
# to true
|
||||
|
||||
# be careful not to nuke an existing dictionary file
|
||||
# extract to a temporary file first
|
||||
|
||||
gunzip -c ${dict}.gz > ${dict}-tmp
|
||||
|
||||
# then move the extracted file to the final location
|
||||
|
||||
mv ${dict}-tmp ${dict}
|
||||
|
||||
# and clean up afterwards
|
||||
|
||||
rm ${dict}.gz
|
||||
curl --silent --location --compressed --time-cond "${dict}" "${source}" | (
|
||||
# uncompress the file on the fly, if it is compressed
|
||||
if [ "${source%.gz}" != "${source}" ]; then
|
||||
gunzip -c > "${tmpfile}" 2>/dev/null
|
||||
else
|
||||
cat > "${tmpfile}"
|
||||
fi
|
||||
) && (
|
||||
mv "${tmpfile}" "${dict}" && chmod a+r "${dict}"
|
||||
) || true
|
||||
}
|
||||
|
||||
# fetch the dictionaries
|
||||
# Update the dictionaries
|
||||
|
||||
fetch_dictionary "@CIFPP_CACHE_DIR@/mmcif_pdbx.dic" "https://mmcif.wwpdb.org/dictionaries/ascii/mmcif_pdbx_v50.dic.gz"
|
||||
fetch_dictionary "@CIFPP_CACHE_DIR@/components.cif" "ftp://ftp.wwpdb.org/pub/pdb/data/monomers/components.cif.gz"
|
||||
update_dictionary "@CIFPP_CACHE_DIR@/components.cif" "https://ftp.wwpdb.org/pub/pdb/data/monomers/components.cif.gz"
|
||||
update_dictionary "@CIFPP_CACHE_DIR@/mmcif_pdbx.dic" "https://mmcif.wwpdb.org/dictionaries/ascii/mmcif_pdbx_v50.dic.gz"
|
||||
update_dictionary "@CIFPP_CACHE_DIR@/mmcif_ma.dic" "https://github.com/ihmwg/ModelCIF/raw/master/dist/mmcif_ma.dic"
|
||||
|
||||
# notify subscribers, will fail on FreeBSD
|
||||
|
||||
if [ -d "@CIFPP_ETC_DIR@/libcifpp/cache-update.d" ] && [ -x /bin/run-parts ]; then
|
||||
run-parts --arg "@CIFPP_CACHE_DIR@" -- "@CIFPP_ETC_DIR@/libcifpp/cache-update.d"
|
||||
fi
|
||||
|
||||
wget -O"@CIFPP_CACHE_DIR@/mmcif_ma.dic" "https://github.com/ihmwg/ModelCIF/raw/master/dist/mmcif_ma.dic"
|
||||
|
||||
Reference in New Issue
Block a user