mirror of
https://github.com/PDB-REDO/libcifpp.git
synced 2026-06-05 06:25:52 +08:00
Compare commits
80 Commits
v7.0.3
...
combined-v
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
228e90a515 | ||
|
|
04c4ecc265 | ||
|
|
3ce3630b50 | ||
|
|
cfefa69c9c | ||
|
|
00638a9e23 | ||
|
|
e241e03a15 | ||
|
|
5e7b52b7de | ||
|
|
0459d344e9 | ||
|
|
71e525cd76 | ||
|
|
1480706d8b | ||
|
|
96655b6d80 | ||
|
|
eed2aa0d0d | ||
|
|
de0c078a23 | ||
|
|
321e995a54 | ||
|
|
da9f1f81d7 | ||
|
|
c6d4477a24 | ||
|
|
523b073cdc | ||
|
|
2591bee21b | ||
|
|
d881ca00c9 | ||
|
|
329dbff474 | ||
|
|
d84a9fe6dc | ||
|
|
dcd812a996 | ||
|
|
6750194d9b | ||
|
|
05865c3d9b | ||
|
|
21e224bf00 | ||
|
|
f401d3fd0c | ||
|
|
fd436871f1 | ||
|
|
fcf7864a4b | ||
|
|
c4003956d9 | ||
|
|
de622b6162 | ||
|
|
41b4bdb90e | ||
|
|
af73cb3ad3 | ||
|
|
240b631963 | ||
|
|
c2a747af8c | ||
|
|
5959647826 | ||
|
|
9542e211bc | ||
|
|
d07890db7f | ||
|
|
ca241bd8f2 | ||
|
|
e444092711 | ||
|
|
a96b1e07f4 | ||
|
|
f48c31bcb5 | ||
|
|
d85ab93a35 | ||
|
|
a6804b5aca | ||
|
|
e4dcb211ee | ||
|
|
a5a5f47f7a | ||
|
|
25c900c387 | ||
|
|
4e95f7b83e | ||
|
|
66ad3b0cee | ||
|
|
e853cd1ca0 | ||
|
|
b9544033c6 | ||
|
|
17840cb8cc | ||
|
|
f85b6d94b8 | ||
|
|
6c32a9f198 | ||
|
|
cefeebbfb8 | ||
|
|
941a015b43 | ||
|
|
ae0e9fbe77 | ||
|
|
3484c3dd2e | ||
|
|
5be8f749bd | ||
|
|
cf484707a0 | ||
|
|
f12e529c0b | ||
|
|
01b90a2ba5 | ||
|
|
cd1e952812 | ||
|
|
996f1e4277 | ||
|
|
2d84694f86 | ||
|
|
65718c64cc | ||
|
|
6e30365f55 | ||
|
|
c0555b6d86 | ||
|
|
1ff9b6c071 | ||
|
|
c1a51a1dfa | ||
|
|
bfbbeb90e7 | ||
|
|
588e075325 | ||
|
|
66717fee68 | ||
|
|
844f52c955 | ||
|
|
e679cd05c1 | ||
|
|
1e72ce4830 | ||
|
|
3bb21c5403 | ||
|
|
6d1be23ad0 | ||
|
|
0472b9a4a4 | ||
|
|
c9acff49f9 | ||
|
|
7cab560595 |
190
CMakeLists.txt
190
CMakeLists.txt
@@ -22,16 +22,17 @@
|
||||
# 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.
|
||||
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
cmake_minimum_required(VERSION 3.23)
|
||||
|
||||
# set the project name
|
||||
project(
|
||||
libcifpp
|
||||
VERSION 7.0.3
|
||||
VERSION 8.0.0
|
||||
LANGUAGES CXX)
|
||||
|
||||
list(PREPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
|
||||
|
||||
include(FindAtomic)
|
||||
include(CheckFunctionExists)
|
||||
include(CheckIncludeFiles)
|
||||
include(CheckLibraryExists)
|
||||
@@ -42,9 +43,10 @@ include(CTest)
|
||||
include(FetchContent)
|
||||
include(ExternalProject)
|
||||
|
||||
set(CXX_EXTENSIONS OFF)
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
# FindBoost, take care of it now.
|
||||
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.30)
|
||||
cmake_policy(SET CMP0167 NEW)
|
||||
endif()
|
||||
|
||||
# When building with ninja-multiconfig, build both debug and release by default
|
||||
if(CMAKE_GENERATOR STREQUAL "Ninja Multi-Config")
|
||||
@@ -71,10 +73,7 @@ if(NOT(BUILD_FOR_CCP4 AND WIN32))
|
||||
option(BUILD_SHARED_LIBS "Build a shared library instead of a static one" OFF)
|
||||
endif()
|
||||
|
||||
if(BUILD_FOR_CCP4)
|
||||
unset(CIFPP_DOWNLOAD_CCD)
|
||||
unset(CIFPP_INSTALL_UPDATE_SCRIPT)
|
||||
else()
|
||||
if(PROJECT_IS_TOP_LEVEL AND NOT BUILD_FOR_CCP4)
|
||||
# Lots of code depend on the availability of the components.cif file
|
||||
option(CIFPP_DOWNLOAD_CCD
|
||||
"Download the CCD file components.cif during installation" ON)
|
||||
@@ -84,6 +83,9 @@ else()
|
||||
option(CIFPP_INSTALL_UPDATE_SCRIPT
|
||||
"Install the script to update CCD and dictionary files" ON)
|
||||
endif()
|
||||
else()
|
||||
unset(CIFPP_DOWNLOAD_CCD)
|
||||
unset(CIFPP_INSTALL_UPDATE_SCRIPT)
|
||||
endif()
|
||||
|
||||
# When CCP4 is sourced in the environment, we can recreate the symmetry
|
||||
@@ -126,6 +128,7 @@ if(WIN32)
|
||||
add_definitions(-D _WIN32_WINNT=0x0501)
|
||||
endif()
|
||||
|
||||
# Man, this is 2024 we're living in...
|
||||
add_definitions(-DNOMINMAX)
|
||||
|
||||
# We do not want to write an export file for all our symbols...
|
||||
@@ -137,6 +140,7 @@ if(MSVC)
|
||||
add_compile_options(/permissive- /bigobj)
|
||||
add_link_options(/NODEFAULTLIB:library)
|
||||
|
||||
# This is dubious...
|
||||
if(BUILD_SHARED_LIBS)
|
||||
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>DLL")
|
||||
else()
|
||||
@@ -189,10 +193,6 @@ if(GXX_LIBSTDCPP)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(CMAKE_THREAD_PREFER_PTHREAD)
|
||||
set(THREADS_PREFER_PTHREAD_FLAG)
|
||||
find_package(Threads)
|
||||
|
||||
if(MSVC)
|
||||
# Avoid linking the shared library of zlib Search ZLIB_ROOT first if it is
|
||||
# set.
|
||||
@@ -221,7 +221,12 @@ if(MSVC)
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
find_package(ZLIB REQUIRED)
|
||||
find_package(ZLIB QUIET)
|
||||
find_package(Threads)
|
||||
|
||||
if(NOT ZLIB_FOUND)
|
||||
message(FATAL_ERROR "The zlib development files were not found you this system, please install them and try again (hint: on debian/ubuntu use apt-get install zlib1g-dev)")
|
||||
endif()
|
||||
|
||||
# Using Eigen3 is a bit of a thing. We don't want to build it completely since
|
||||
# we only need a couple of header files. Nothing special. But often, eigen3 is
|
||||
@@ -232,26 +237,17 @@ if(Eigen3_FOUND AND TARGET Eigen3::Eigen)
|
||||
get_target_property(EIGEN_INCLUDE_DIR Eigen3::Eigen
|
||||
INTERFACE_INCLUDE_DIRECTORIES)
|
||||
else()
|
||||
# Create a private copy of eigen3 and populate it only, no need to build
|
||||
FetchContent_Declare(
|
||||
my-eigen3
|
||||
# Use ExternalProject since FetchContent always tries to install the result...
|
||||
ExternalProject_Add(my-eigen3
|
||||
GIT_REPOSITORY https://gitlab.com/libeigen/eigen.git
|
||||
GIT_TAG 3.4.0)
|
||||
|
||||
FetchContent_GetProperties(my-eigen3)
|
||||
|
||||
if(NOT my-eigen3_POPULATED)
|
||||
FetchContent_Populate(my-eigen3)
|
||||
endif()
|
||||
|
||||
set(EIGEN_INCLUDE_DIR ${my-eigen3_SOURCE_DIR})
|
||||
GIT_TAG 3.4.0
|
||||
INSTALL_COMMAND "")
|
||||
|
||||
ExternalProject_Get_Property(my-eigen3 SOURCE_DIR)
|
||||
set(EIGEN_INCLUDE_DIR ${SOURCE_DIR})
|
||||
endif()
|
||||
|
||||
include(FindFilesystem)
|
||||
list(APPEND CIFPP_REQUIRED_LIBRARIES ${STDCPPFS_LIBRARY})
|
||||
|
||||
include(FindAtomic)
|
||||
list(APPEND CIFPP_REQUIRED_LIBRARIES ${STDCPPATOMIC_LIBRARY})
|
||||
message(STATUS "Eigen include dir is ${EIGEN_INCLUDE_DIR}")
|
||||
|
||||
# Create a revision file, containing the current git version info
|
||||
include(VersionString)
|
||||
@@ -263,6 +259,8 @@ if(CIFPP_RECREATE_SYMOP_DATA)
|
||||
add_executable(symop-map-generator
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/src/symop-map-generator.cpp")
|
||||
|
||||
target_compile_features(symop-map-generator PUBLIC cxx_std_20)
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/src/symop_table_data.hpp
|
||||
COMMAND
|
||||
@@ -305,33 +303,42 @@ set(project_sources
|
||||
|
||||
set(project_headers
|
||||
include/cif++.hpp
|
||||
include/cif++/utilities.hpp
|
||||
include/cif++/item.hpp
|
||||
include/cif++/atom_type.hpp
|
||||
include/cif++/category.hpp
|
||||
include/cif++/compound.hpp
|
||||
include/cif++/condition.hpp
|
||||
include/cif++/datablock.hpp
|
||||
include/cif++/dictionary_parser.hpp
|
||||
include/cif++/exports.hpp
|
||||
include/cif++/file.hpp
|
||||
include/cif++/validate.hpp
|
||||
include/cif++/iterator.hpp
|
||||
include/cif++/parser.hpp
|
||||
include/cif++/format.hpp
|
||||
include/cif++/forward_decl.hpp
|
||||
include/cif++/dictionary_parser.hpp
|
||||
include/cif++/condition.hpp
|
||||
include/cif++/category.hpp
|
||||
include/cif++/row.hpp
|
||||
include/cif++/atom_type.hpp
|
||||
include/cif++/compound.hpp
|
||||
include/cif++/point.hpp
|
||||
include/cif++/symmetry.hpp
|
||||
include/cif++/gzio.hpp
|
||||
include/cif++/item.hpp
|
||||
include/cif++/iterator.hpp
|
||||
include/cif++/matrix.hpp
|
||||
include/cif++/model.hpp
|
||||
include/cif++/pdb.hpp
|
||||
include/cif++/parser.hpp
|
||||
include/cif++/pdb/cif2pdb.hpp
|
||||
include/cif++/pdb.hpp
|
||||
include/cif++/pdb/io.hpp
|
||||
include/cif++/pdb/pdb2cif.hpp
|
||||
include/cif++/pdb/tls.hpp)
|
||||
include/cif++/pdb/tls.hpp
|
||||
include/cif++/point.hpp
|
||||
include/cif++/row.hpp
|
||||
include/cif++/symmetry.hpp
|
||||
include/cif++/text.hpp
|
||||
include/cif++/utilities.hpp
|
||||
include/cif++/validate.hpp
|
||||
)
|
||||
|
||||
add_library(cifpp STATIC)
|
||||
add_library(cifpp)
|
||||
add_library(cifpp::cifpp ALIAS cifpp)
|
||||
|
||||
if(TARGET my-eigen3)
|
||||
add_dependencies(cifpp my-eigen3)
|
||||
endif()
|
||||
|
||||
target_sources(cifpp
|
||||
PRIVATE ${project_sources}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/symop_table_data.hpp
|
||||
@@ -369,8 +376,7 @@ target_include_directories(
|
||||
"$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>"
|
||||
PRIVATE "${BOOST_REGEX_INCLUDE_DIR}" "${EIGEN_INCLUDE_DIR}")
|
||||
|
||||
target_link_libraries(cifpp PUBLIC Threads::Threads ZLIB::ZLIB
|
||||
${CIFPP_REQUIRED_LIBRARIES})
|
||||
target_link_libraries(cifpp PUBLIC Threads::Threads ZLIB::ZLIB $<$<TARGET_EXISTS:std::atomic>:std::atomic>)
|
||||
|
||||
if(CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang")
|
||||
target_link_options(cifpp PRIVATE -undefined dynamic_lookup)
|
||||
@@ -441,6 +447,11 @@ endif()
|
||||
|
||||
if(CIFPP_DATA_DIR)
|
||||
target_compile_definitions(cifpp PUBLIC DATA_DIR="${CIFPP_DATA_DIR}")
|
||||
set_target_properties(cifpp PROPERTIES CIFPP_DATA_DIR ${CIFPP_DATA_DIR})
|
||||
endif()
|
||||
|
||||
if(NOT PROJECT_IS_TOP_LEVEL)
|
||||
set(CIFPP_SHARE_DIR ${CIFPP_DATA_DIR} PARENT_SCOPE)
|
||||
endif()
|
||||
|
||||
if(UNIX AND NOT BUILD_FOR_CCP4)
|
||||
@@ -491,20 +502,15 @@ install(EXPORT cifpp
|
||||
FILE "cifpp-targets.cmake"
|
||||
DESTINATION lib/cmake/cifpp)
|
||||
|
||||
if(CIFPP_DATA_DIR AND CIFPP_DOWNLOAD_CCD)
|
||||
install(
|
||||
FILES ${CMAKE_CURRENT_SOURCE_DIR}/rsrc/mmcif_ddl.dic
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/rsrc/mmcif_pdbx.dic
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/rsrc/mmcif_ma.dic ${COMPONENTS_CIF}
|
||||
DESTINATION ${CIFPP_DATA_DIR})
|
||||
endif()
|
||||
install(
|
||||
FILES ${CMAKE_CURRENT_SOURCE_DIR}/rsrc/mmcif_ddl.dic
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/rsrc/mmcif_pdbx.dic
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/rsrc/mmcif_ma.dic
|
||||
DESTINATION ${CMAKE_INSTALL_DATADIR}/libcifpp)
|
||||
|
||||
if(CIFPP_CACHE_DIR AND CIFPP_DOWNLOAD_CCD)
|
||||
install(
|
||||
FILES ${CMAKE_CURRENT_SOURCE_DIR}/rsrc/mmcif_ddl.dic
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/rsrc/mmcif_pdbx.dic
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/rsrc/mmcif_ma.dic ${COMPONENTS_CIF}
|
||||
DESTINATION ${CIFPP_CACHE_DIR})
|
||||
if(CIFPP_DATA_DIR AND CIFPP_DOWNLOAD_CCD)
|
||||
install(FILES ${COMPONENTS_CIF}
|
||||
DESTINATION ${CMAKE_INSTALL_DATADIR}/libcifpp)
|
||||
endif()
|
||||
|
||||
set(CONFIG_TEMPLATE_FILE ${CMAKE_CURRENT_SOURCE_DIR}/cmake/cifpp-config.cmake.in)
|
||||
@@ -535,60 +541,42 @@ write_basic_package_version_file(
|
||||
VERSION ${PROJECT_VERSION}
|
||||
COMPATIBILITY AnyNewerVersion)
|
||||
|
||||
# In case we're included as sub_directory:
|
||||
if(NOT PROJECT_IS_TOP_LEVEL)
|
||||
set(CIFPP_SHARE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/rsrc PARENT_SCOPE)
|
||||
endif()
|
||||
|
||||
if(BUILD_TESTING)
|
||||
if(BUILD_TESTING AND PROJECT_IS_TOP_LEVEL)
|
||||
add_subdirectory(test)
|
||||
endif()
|
||||
|
||||
# Optionally install the update scripts for CCD and dictionary files
|
||||
if(CIFPP_INSTALL_UPDATE_SCRIPT)
|
||||
if(${CMAKE_SYSTEM_NAME} STREQUAL "Linux" OR ${CMAKE_SYSTEM_NAME} STREQUAL
|
||||
"GNU")
|
||||
if("${CMAKE_INSTALL_PREFIX}" STREQUAL "/usr/local")
|
||||
set(CIFPP_CRON_DIR
|
||||
"/etc/cron.weekly"
|
||||
CACHE PATH "The cron directory, for the update script")
|
||||
else()
|
||||
set(CIFPP_CRON_DIR
|
||||
"${CIFPP_ETC_DIR}/cron.weekly"
|
||||
CACHE PATH "The cron directory, for the update script")
|
||||
endif()
|
||||
elseif(${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD")
|
||||
set(CIFPP_CRON_DIR
|
||||
"${CIFPP_ETC_DIR}/periodic/weekly"
|
||||
CACHE PATH "The cron directory, for the update script")
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/tools/update-libcifpp-data.in
|
||||
update-libcifpp-data @ONLY)
|
||||
|
||||
if(${CMAKE_SYSTEM_NAME} STREQUAL "Linux" OR
|
||||
${CMAKE_SYSTEM_NAME} STREQUAL "GNU" OR
|
||||
${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD")
|
||||
install(
|
||||
FILES ${CMAKE_CURRENT_BINARY_DIR}/update-libcifpp-data
|
||||
DESTINATION ${CMAKE_INSTALL_SYSCONFDIR}/cron.weekly
|
||||
PERMISSIONS OWNER_EXECUTE OWNER_READ GROUP_EXECUTE GROUP_READ WORLD_EXECUTE
|
||||
WORLD_READ)
|
||||
else()
|
||||
message(FATAL_ERROR "Don't know where to install the update script")
|
||||
endif()
|
||||
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/tools/update-libcifpp-data.in
|
||||
update-libcifpp-data @ONLY)
|
||||
install(
|
||||
FILES ${CMAKE_CURRENT_BINARY_DIR}/update-libcifpp-data
|
||||
DESTINATION ${CIFPP_CRON_DIR}
|
||||
PERMISSIONS OWNER_EXECUTE OWNER_READ GROUP_EXECUTE GROUP_READ WORLD_EXECUTE
|
||||
WORLD_READ)
|
||||
|
||||
install(DIRECTORY DESTINATION ${CIFPP_CACHE_DIR})
|
||||
|
||||
# a config file, to make it complete
|
||||
if(NOT EXISTS "${CIFPP_ETC_DIR}/libcifpp.conf")
|
||||
# install(DIRECTORY DESTINATION "${CMAKE_INSTALL_LOCALSTATEDIR}/libcifpp")
|
||||
if(NOT EXISTS "${CMAKE_INSTALL_SYSCONFDIR}/libcifpp.conf")
|
||||
file(
|
||||
WRITE ${CMAKE_CURRENT_BINARY_DIR}/libcifpp.conf
|
||||
[[# Uncomment the next line to enable automatic updates
|
||||
# update=true
|
||||
]])
|
||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/libcifpp.conf
|
||||
DESTINATION "${CIFPP_ETC_DIR}")
|
||||
DESTINATION ${CMAKE_INSTALL_SYSCONFDIR})
|
||||
install(
|
||||
CODE "message(\"A configuration file has been written to ${CIFPP_ETC_DIR}/libcifpp.conf, please edit this file to enable automatic updates\")"
|
||||
)
|
||||
|
||||
install(DIRECTORY DESTINATION "${CIFPP_ETC_DIR}/libcifpp/cache-update.d")
|
||||
install(DIRECTORY DESTINATION ${CMAKE_INSTALL_SYSCONFDIR}/libcifpp/cache-update.d)
|
||||
endif()
|
||||
|
||||
target_compile_definitions(cifpp PUBLIC CACHE_DIR="${CIFPP_CACHE_DIR}")
|
||||
@@ -597,13 +585,3 @@ endif()
|
||||
if(BUILD_DOCUMENTATION)
|
||||
add_subdirectory(docs)
|
||||
endif()
|
||||
|
||||
set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE")
|
||||
set(CPACK_SOURCE_TGZ ON)
|
||||
set(CPACK_SOURCE_TBZ2 OFF)
|
||||
set(CPACK_SOURCE_TXZ OFF)
|
||||
set(CPACK_SOURCE_TZ OFF)
|
||||
set(CPACK_SOURCE_IGNORE_FILES "/rsrc/components.cif;/build;/.vscode;/.git")
|
||||
set(CPACK_PACKAGE_FILE_NAME "${PROJECT_NAME}-${PROJECT_VERSION}")
|
||||
set(CPACK_SOURCE_PACKAGE_FILE_NAME ${CPACK_PACKAGE_FILE_NAME})
|
||||
include(CPack)
|
||||
|
||||
@@ -52,7 +52,7 @@ int main(int argc, char *argv[])
|
||||
|
||||
if (file.empty())
|
||||
{
|
||||
std::cerr << "Empty file" << std::endl;
|
||||
std::cerr << "Empty file\n";
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@@ -66,8 +66,8 @@ int main(int argc, char *argv[])
|
||||
auto n = atom_site.count(cif::key("label_atom_id") == "OXT");
|
||||
|
||||
std::cout << "File contains " << atom_site.size() << " atoms of which "
|
||||
<< n << (n == 1 ? " is" : " are") << " OXT" << std::endl
|
||||
<< "residues with an OXT are:" << std::endl;
|
||||
<< n << (n == 1 ? " is" : " are") << " OXT\n"
|
||||
<< "residues with an OXT are:\n";
|
||||
|
||||
// Loop over all atoms with atom-id "OXT" and print out some info.
|
||||
// That info is extracted using structured binding in C++
|
||||
@@ -76,7 +76,7 @@ int main(int argc, char *argv[])
|
||||
cif::key("label_atom_id") == "OXT",
|
||||
"label_asym_id", "label_comp_id", "label_seq_id"))
|
||||
{
|
||||
std::cout << asym << ' ' << comp << ' ' << seqnr << std::endl;
|
||||
std::cout << asym << ' ' << comp << ' ' << seqnr << '\n';
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
35
changelog
35
changelog
@@ -1,3 +1,38 @@
|
||||
Version 8.0.0
|
||||
- A dictionary is for a datablock and a file can have
|
||||
datablocks with differing dictionaries.
|
||||
|
||||
Version 7.0.10
|
||||
- Deal with missing _entity.type in reconstructing mmCIF files
|
||||
- Replace code creating quaternions from rotation matrices
|
||||
that might sometimes give incorrect results. Or at least,
|
||||
the test code failed on this particular kind of code. Sometimes.
|
||||
|
||||
Version 7.0.9
|
||||
- Using cif::file::load_dictionary it is now possible to
|
||||
load a dictionary along with its extensions in one go.
|
||||
E.g. file.load_dictionary("mmcif_pdbx;dssp-extension")
|
||||
- Fix in compound factory to avoid errors with lower case
|
||||
compound id's
|
||||
- Fix sac_parser's index to be case insensitive
|
||||
|
||||
Version 7.0.8
|
||||
- Fix PDB Remark 3 parser
|
||||
- Added three way comparison for point
|
||||
|
||||
Version 7.0.7
|
||||
- Set CIFPP_DATA_DIR on target cifpp for use in projects that include
|
||||
libcifpp directly
|
||||
|
||||
Version 7.0.6
|
||||
- Fix linking to std::atomic
|
||||
|
||||
Version 7.0.5
|
||||
- Fix case where category index was not updated for updated value
|
||||
|
||||
Version 7.0.4
|
||||
- Do not install headers and library in case we're not the top project
|
||||
|
||||
Version 7.0.3
|
||||
- Fix installation, write exports.hpp again
|
||||
|
||||
|
||||
@@ -1,75 +0,0 @@
|
||||
# Simplistic reimplementation of https://github.com/vector-of-bool/CMakeCM/blob/master/modules/FindFilesystem.cmake
|
||||
|
||||
if(TARGET std::filesystem)
|
||||
return()
|
||||
endif()
|
||||
|
||||
cmake_minimum_required(VERSION 3.10)
|
||||
|
||||
include(CMakePushCheckState)
|
||||
include(CheckIncludeFileCXX)
|
||||
include(CheckCXXSourceCompiles)
|
||||
|
||||
cmake_push_check_state()
|
||||
|
||||
check_include_file_cxx("filesystem" _CXX_FILESYSTEM_HAVE_HEADER)
|
||||
mark_as_advanced(_CXX_FILESYSTEM_HAVE_HEADER)
|
||||
|
||||
set(code [[
|
||||
#include <cstdlib>
|
||||
#include <filesystem>
|
||||
|
||||
int main() {
|
||||
auto cwd = std::filesystem::current_path();
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
]])
|
||||
|
||||
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS_EQUAL 8.4.0)
|
||||
# >> https://stackoverflow.com/questions/63902528/program-crashes-when-filesystempath-is-destroyed
|
||||
set(CXX_FILESYSTEM_NO_LINK_NEEDED 0)
|
||||
else()
|
||||
# Check a simple filesystem program without any linker flags
|
||||
check_cxx_source_compiles("${code}" CXX_FILESYSTEM_NO_LINK_NEEDED)
|
||||
endif()
|
||||
|
||||
if(CXX_FILESYSTEM_NO_LINK_NEEDED)
|
||||
set(_found 1)
|
||||
else()
|
||||
set(prev_libraries ${CMAKE_REQUIRED_LIBRARIES})
|
||||
# Add the libstdc++ flag
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${prev_libraries} -lstdc++fs)
|
||||
check_cxx_source_compiles("${code}" CXX_FILESYSTEM_STDCPPFS_NEEDED)
|
||||
set(_found ${CXX_FILESYSTEM_STDCPPFS_NEEDED})
|
||||
if(NOT CXX_FILESYSTEM_STDCPPFS_NEEDED)
|
||||
# Try the libc++ flag
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${prev_libraries} -lc++fs)
|
||||
check_cxx_source_compiles("${code}" CXX_FILESYSTEM_CPPFS_NEEDED)
|
||||
set(_found ${CXX_FILESYSTEM_CPPFS_NEEDED})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(_found)
|
||||
add_library(std::filesystem INTERFACE IMPORTED)
|
||||
set_property(TARGET std::filesystem APPEND PROPERTY INTERFACE_COMPILE_FEATURES cxx_std_17)
|
||||
|
||||
if(CXX_FILESYSTEM_NO_LINK_NEEDED)
|
||||
# Nothing to add...
|
||||
elseif(CXX_FILESYSTEM_STDCPPFS_NEEDED)
|
||||
set_target_properties(std::filesystem PROPERTIES IMPORTED_LIBNAME stdc++fs)
|
||||
set(STDCPPFS_LIBRARY stdc++fs)
|
||||
elseif(CXX_FILESYSTEM_CPPFS_NEEDED)
|
||||
set_target_properties(std::filesystem PROPERTIES IMPORTED_LIBNAME c++fs)
|
||||
set(STDCPPFS_LIBRARY c++fs)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
cmake_pop_check_state()
|
||||
|
||||
set(Filesystem_FOUND ${_found} CACHE BOOL "TRUE if we can run a program using std::filesystem" FORCE)
|
||||
mark_as_advanced(Filesystem_FOUND)
|
||||
|
||||
if(Filesystem_FIND_REQUIRED AND NOT Filesystem_FOUND)
|
||||
message(FATAL_ERROR "Cannot run simple program using std::filesystem")
|
||||
endif()
|
||||
|
||||
@@ -13,7 +13,7 @@ int main(int argc, char *argv[])
|
||||
exit(1);
|
||||
}
|
||||
|
||||
cif::file file = cif::pdb::read(argv[1]);
|
||||
cif::file file(argv[1]);
|
||||
|
||||
if (file.empty())
|
||||
{
|
||||
|
||||
@@ -200,7 +200,7 @@ enum class radius_type
|
||||
};
|
||||
|
||||
/// @brief The number of radii per element which can be requested from atom_type_info
|
||||
constexpr size_t kRadiusTypeCount = static_cast<size_t>(radius_type::type_count);
|
||||
constexpr std::size_t kRadiusTypeCount = static_cast<std::size_t>(radius_type::type_count);
|
||||
|
||||
/// An enum used to select either the effective or the crystal radius of an ion.
|
||||
/// See explanation on Wikipedia: https://en.wikipedia.org/wiki/Ionic_radius
|
||||
@@ -276,7 +276,7 @@ class atom_type_traits
|
||||
{
|
||||
if (type >= radius_type::type_count)
|
||||
throw std::invalid_argument("invalid radius requested");
|
||||
return m_info->radii[static_cast<size_t>(type)] / 100.f;
|
||||
return m_info->radii[static_cast<std::size_t>(type)] / 100.f;
|
||||
}
|
||||
|
||||
/// \brief Return the radius for a charged version of this atom in a solid crystal
|
||||
|
||||
@@ -178,7 +178,7 @@ class category
|
||||
/// @brief Set the validator for this category to @a v
|
||||
/// @param v The category_validator to assign. A nullptr value is allowed.
|
||||
/// @param db The enclosing @ref datablock
|
||||
void set_validator(const validator *v, datablock &db);
|
||||
void set_validator(const validator_base *v, datablock &db);
|
||||
|
||||
/// @brief Update the links in this category
|
||||
/// @param db The enclosing @ref datablock
|
||||
@@ -186,7 +186,7 @@ class category
|
||||
|
||||
/// @brief Return the global @ref validator for the data
|
||||
/// @return The @ref validator or nullptr if not assigned
|
||||
const validator *get_validator() const { return m_validator; }
|
||||
const validator_base *get_validator() const { return m_validator; }
|
||||
|
||||
/// @brief Return the category validator for this category
|
||||
/// @return The @ref category_validator or nullptr if not assigned
|
||||
@@ -293,15 +293,15 @@ class category
|
||||
}
|
||||
|
||||
/// Return a count of the rows in this container
|
||||
size_t size() const
|
||||
std::size_t size() const
|
||||
{
|
||||
return std::distance(cbegin(), cend());
|
||||
}
|
||||
|
||||
/// Return the theoretical maximum number or rows that can be stored
|
||||
size_t max_size() const
|
||||
std::size_t max_size() const
|
||||
{
|
||||
return std::numeric_limits<size_t>::max(); // this is a bit optimistic, I guess
|
||||
return std::numeric_limits<std::size_t>::max(); // this is a bit optimistic, I guess
|
||||
}
|
||||
|
||||
/// Return true if the category is empty
|
||||
@@ -831,9 +831,9 @@ class category
|
||||
/// @brief Return the total number of rows that match condition @a cond
|
||||
/// @param cond The condition to match
|
||||
/// @return The count
|
||||
size_t count(condition &&cond) const
|
||||
std::size_t count(condition &&cond) const
|
||||
{
|
||||
size_t result = 0;
|
||||
std::size_t result = 0;
|
||||
|
||||
if (cond)
|
||||
{
|
||||
@@ -903,14 +903,14 @@ class category
|
||||
/// @brief Erase all rows that match condition @a cond
|
||||
/// @param cond The condition
|
||||
/// @return The number of rows that have been erased
|
||||
size_t erase(condition &&cond);
|
||||
std::size_t erase(condition &&cond);
|
||||
|
||||
/// @brief Erase all rows that match condition @a cond calling
|
||||
/// the visitor function @a visit for each before actually erasing it.
|
||||
/// @param cond The condition
|
||||
/// @param visit The visitor function
|
||||
/// @return The number of rows that have been erased
|
||||
size_t erase(condition &&cond, std::function<void(row_handle)> &&visit);
|
||||
std::size_t erase(condition &&cond, std::function<void(row_handle)> &&visit);
|
||||
|
||||
/// @brief Emplace the values in @a ri in a new row
|
||||
/// @param ri An object containing the values to insert
|
||||
@@ -1285,7 +1285,7 @@ class category
|
||||
|
||||
std::string m_name;
|
||||
std::vector<item_entry> m_items;
|
||||
const validator *m_validator = nullptr;
|
||||
const validator_base *m_validator = nullptr;
|
||||
const category_validator *m_cat_validator = nullptr;
|
||||
std::vector<link> m_parent_links, m_child_links;
|
||||
bool m_cascade = true;
|
||||
|
||||
@@ -138,7 +138,7 @@ struct compound_bond
|
||||
/// This information is derived from the CDD by default.
|
||||
///
|
||||
/// To create compounds, you use the factory method. You can add your own
|
||||
/// compound definitions by calling the addExtraComponents function and
|
||||
/// compound definitions by calling the push_dictionary function and
|
||||
/// pass it a valid CCD formatted file.
|
||||
|
||||
class compound
|
||||
@@ -180,8 +180,7 @@ class compound
|
||||
friend class local_compound_factory_impl;
|
||||
|
||||
compound(cif::datablock &db);
|
||||
compound(cif::datablock &db, int);
|
||||
|
||||
|
||||
std::string m_id;
|
||||
std::string m_name;
|
||||
std::string m_type;
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#include "cif++/row.hpp"
|
||||
|
||||
#include <cassert>
|
||||
#include <concepts>
|
||||
#include <functional>
|
||||
#include <iostream>
|
||||
#include <regex>
|
||||
@@ -470,6 +471,106 @@ namespace detail
|
||||
std::optional<row_handle> m_single_hit;
|
||||
};
|
||||
|
||||
struct key_equals_number_condition_impl : public condition_impl
|
||||
{
|
||||
key_equals_number_condition_impl(const std::string &name, double v)
|
||||
: m_item_name(name)
|
||||
, m_value(v)
|
||||
{
|
||||
}
|
||||
|
||||
condition_impl *prepare(const category &c) override;
|
||||
|
||||
bool test(row_handle r) const override
|
||||
{
|
||||
return m_single_hit.has_value() ? *m_single_hit == r : r[m_item_ix].compare(m_value) == 0;
|
||||
}
|
||||
|
||||
void str(std::ostream &os) const override
|
||||
{
|
||||
os << m_item_name << " == " << m_value;
|
||||
}
|
||||
|
||||
virtual std::optional<row_handle> single() const override
|
||||
{
|
||||
return m_single_hit;
|
||||
}
|
||||
|
||||
virtual bool equals(const condition_impl *rhs) const override
|
||||
{
|
||||
if (typeid(*rhs) == typeid(key_equals_number_condition_impl))
|
||||
{
|
||||
auto ri = static_cast<const key_equals_number_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 item_names 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_name == ri->m_item_name;
|
||||
}
|
||||
return this == rhs;
|
||||
}
|
||||
|
||||
std::string m_item_name;
|
||||
uint16_t m_item_ix = 0;
|
||||
double m_value;
|
||||
std::optional<row_handle> m_single_hit;
|
||||
};
|
||||
|
||||
struct key_equals_number_or_empty_condition_impl : public condition_impl
|
||||
{
|
||||
key_equals_number_or_empty_condition_impl(key_equals_number_condition_impl *equals)
|
||||
: m_item_name(equals->m_item_name)
|
||||
, m_value(equals->m_value)
|
||||
, m_single_hit(equals->m_single_hit)
|
||||
{
|
||||
}
|
||||
|
||||
condition_impl *prepare(const category &c) override
|
||||
{
|
||||
m_item_ix = get_item_ix(c, m_item_name);
|
||||
return this;
|
||||
}
|
||||
|
||||
bool test(row_handle r) const override
|
||||
{
|
||||
bool result = false;
|
||||
if (m_single_hit.has_value())
|
||||
result = *m_single_hit == r;
|
||||
else
|
||||
result = r[m_item_ix].empty() or r[m_item_ix].compare(m_value) == 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
void str(std::ostream &os) const override
|
||||
{
|
||||
os << '(' << m_item_name << " == " << m_value << " OR " << m_item_name << " IS NULL)";
|
||||
}
|
||||
|
||||
virtual std::optional<row_handle> single() const override
|
||||
{
|
||||
return m_single_hit;
|
||||
}
|
||||
|
||||
virtual bool equals(const condition_impl *rhs) const override
|
||||
{
|
||||
if (typeid(*rhs) == typeid(key_equals_number_or_empty_condition_impl))
|
||||
{
|
||||
auto ri = static_cast<const key_equals_number_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 item_names 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_name == ri->m_item_name;
|
||||
}
|
||||
return this == rhs;
|
||||
}
|
||||
|
||||
std::string m_item_name;
|
||||
uint16_t m_item_ix = 0;
|
||||
double m_value;
|
||||
std::optional<row_handle> m_single_hit;
|
||||
};
|
||||
|
||||
struct key_compare_condition_impl : public condition_impl
|
||||
{
|
||||
template <typename COMP>
|
||||
@@ -876,7 +977,8 @@ inline condition operator or(condition &&a, condition &&b)
|
||||
if (ci->m_item_name == ce->m_item_name)
|
||||
return condition(new detail::key_equals_or_empty_condition_impl(ci));
|
||||
}
|
||||
else if (typeid(*b.m_impl) == typeid(detail::key_equals_condition_impl) and
|
||||
|
||||
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);
|
||||
@@ -886,6 +988,26 @@ inline condition operator or(condition &&a, condition &&b)
|
||||
return condition(new detail::key_equals_or_empty_condition_impl(ci));
|
||||
}
|
||||
|
||||
if (typeid(*a.m_impl) == typeid(detail::key_equals_number_condition_impl) and
|
||||
typeid(*b.m_impl) == typeid(detail::key_is_empty_condition_impl))
|
||||
{
|
||||
auto ci = static_cast<detail::key_equals_number_condition_impl *>(a.m_impl);
|
||||
auto ce = static_cast<detail::key_is_empty_condition_impl *>(b.m_impl);
|
||||
|
||||
if (ci->m_item_name == ce->m_item_name)
|
||||
return condition(new detail::key_equals_number_or_empty_condition_impl(ci));
|
||||
}
|
||||
|
||||
if (typeid(*b.m_impl) == typeid(detail::key_equals_number_condition_impl) and
|
||||
typeid(*a.m_impl) == typeid(detail::key_is_empty_condition_impl))
|
||||
{
|
||||
auto ci = static_cast<detail::key_equals_number_condition_impl *>(b.m_impl);
|
||||
auto ce = static_cast<detail::key_is_empty_condition_impl *>(a.m_impl);
|
||||
|
||||
if (ci->m_item_name == ce->m_item_name)
|
||||
return condition(new detail::key_equals_number_or_empty_condition_impl(ci));
|
||||
}
|
||||
|
||||
return condition(new detail::or_condition_impl(std::move(a), std::move(b)));
|
||||
}
|
||||
|
||||
@@ -959,13 +1081,16 @@ struct key
|
||||
std::string m_item_name; ///< The item name
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Operator to create an equals condition based on a key @a key and a value @a v
|
||||
*/
|
||||
template <typename T>
|
||||
concept Numeric = ((std::is_floating_point_v<T> or std::is_integral_v<T>) and not std::is_same_v<T, bool>);
|
||||
|
||||
/**
|
||||
* @brief Operator to create an equals condition based on a key @a key and a numeric value @a v
|
||||
*/
|
||||
template <Numeric T>
|
||||
condition operator==(const key &key, const T &v)
|
||||
{
|
||||
return condition(new detail::key_equals_condition_impl({ key.m_item_name, v }));
|
||||
return condition(new detail::key_equals_number_condition_impl(key.m_item_name, v));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -979,6 +1104,16 @@ inline condition operator==(const key &key, std::string_view value)
|
||||
return condition(new detail::key_is_empty_condition_impl(key.m_item_name));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Operator to create an equals condition based on a key @a key and a value @a value
|
||||
*/
|
||||
template <typename T>
|
||||
requires std::is_same_v<T, bool>
|
||||
inline condition operator==(const key &key, T value)
|
||||
{
|
||||
return condition(new detail::key_equals_condition_impl({ key.m_item_name, value ? "y" : "n" }));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Operator to create a not equals condition based on a key @a key and a value @a v
|
||||
*/
|
||||
@@ -999,7 +1134,7 @@ inline condition operator!=(const key &key, std::string_view value)
|
||||
/**
|
||||
* @brief Operator to create a greater than condition based on a key @a key and a value @a v
|
||||
*/
|
||||
template <typename T>
|
||||
template <Numeric T>
|
||||
condition operator>(const key &key, const T &v)
|
||||
{
|
||||
std::ostringstream s;
|
||||
@@ -1007,14 +1142,14 @@ condition operator>(const key &key, const T &v)
|
||||
|
||||
return condition(new detail::key_compare_condition_impl(
|
||||
key.m_item_name, [item_name = key.m_item_name, v](row_handle r, bool icase)
|
||||
{ return r[item_name].template compare<T>(v, icase) > 0; },
|
||||
{ return r[item_name].compare(v) > 0; },
|
||||
s.str()));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Operator to create a greater than or equals condition based on a key @a key and a value @a v
|
||||
*/
|
||||
template <typename T>
|
||||
template <Numeric T>
|
||||
condition operator>=(const key &key, const T &v)
|
||||
{
|
||||
std::ostringstream s;
|
||||
@@ -1022,14 +1157,14 @@ condition operator>=(const key &key, const T &v)
|
||||
|
||||
return condition(new detail::key_compare_condition_impl(
|
||||
key.m_item_name, [item_name = key.m_item_name, v](row_handle r, bool icase)
|
||||
{ return r[item_name].template compare<T>(v, icase) >= 0; },
|
||||
{ return r[item_name].compare(v) >= 0; },
|
||||
s.str()));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Operator to create a less than condition based on a key @a key and a value @a v
|
||||
*/
|
||||
template <typename T>
|
||||
template <Numeric T>
|
||||
condition operator<(const key &key, const T &v)
|
||||
{
|
||||
std::ostringstream s;
|
||||
@@ -1037,14 +1172,14 @@ condition operator<(const key &key, const T &v)
|
||||
|
||||
return condition(new detail::key_compare_condition_impl(
|
||||
key.m_item_name, [item_name = key.m_item_name, v](row_handle r, bool icase)
|
||||
{ return r[item_name].template compare<T>(v, icase) < 0; },
|
||||
{ return r[item_name].compare(v) < 0; },
|
||||
s.str()));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Operator to create a less than or equals condition based on a key @a key and a value @a v
|
||||
*/
|
||||
template <typename T>
|
||||
template <Numeric T>
|
||||
condition operator<=(const key &key, const T &v)
|
||||
{
|
||||
std::ostringstream s;
|
||||
@@ -1052,7 +1187,63 @@ condition operator<=(const key &key, const T &v)
|
||||
|
||||
return condition(new detail::key_compare_condition_impl(
|
||||
key.m_item_name, [item_name = key.m_item_name, v](row_handle r, bool icase)
|
||||
{ return r[item_name].template compare<T>(v, icase) <= 0; },
|
||||
{ return r[item_name].compare(v) <= 0; },
|
||||
s.str()));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Operator to create a greater than condition based on a key @a key and a value @a v
|
||||
*/
|
||||
inline condition operator>(const key &key, std::string_view v)
|
||||
{
|
||||
std::ostringstream s;
|
||||
s << " > " << v;
|
||||
|
||||
return condition(new detail::key_compare_condition_impl(
|
||||
key.m_item_name, [item_name = key.m_item_name, v](row_handle r, bool icase)
|
||||
{ return r[item_name].compare(v, icase) > 0; },
|
||||
s.str()));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Operator to create a greater than or equals condition based on a key @a key and a value @a v
|
||||
*/
|
||||
inline condition operator>=(const key &key, std::string_view v)
|
||||
{
|
||||
std::ostringstream s;
|
||||
s << " >= " << v;
|
||||
|
||||
return condition(new detail::key_compare_condition_impl(
|
||||
key.m_item_name, [item_name = key.m_item_name, v](row_handle r, bool icase)
|
||||
{ return r[item_name].compare(v, icase) >= 0; },
|
||||
s.str()));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Operator to create a less than condition based on a key @a key and a value @a v
|
||||
*/
|
||||
inline condition operator<(const key &key, std::string_view v)
|
||||
{
|
||||
std::ostringstream s;
|
||||
s << " < " << v;
|
||||
|
||||
return condition(new detail::key_compare_condition_impl(
|
||||
key.m_item_name, [item_name = key.m_item_name, v](row_handle r, bool icase)
|
||||
{ return r[item_name].compare(v, icase) < 0; },
|
||||
s.str()));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Operator to create a less than or equals condition based on a key @a key and a value @a v
|
||||
*/
|
||||
inline condition operator<=(const key &key, std::string_view v)
|
||||
{
|
||||
std::ostringstream s;
|
||||
s << " <= " << v;
|
||||
|
||||
return condition(new detail::key_compare_condition_impl(
|
||||
key.m_item_name, [item_name = key.m_item_name, v](row_handle r, bool icase)
|
||||
{ return r[item_name].compare(v, icase) <= 0; },
|
||||
s.str()));
|
||||
}
|
||||
|
||||
@@ -1093,6 +1284,19 @@ condition operator==(const key &key, const std::optional<T> &v)
|
||||
return condition(new detail::key_is_empty_condition_impl(key.m_item_name));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Create a condition to search any item for a value @a v if @a v contains a value
|
||||
* compare to null if not.
|
||||
*/
|
||||
template <typename T>
|
||||
condition operator!=(const key &key, const std::optional<T> &v)
|
||||
{
|
||||
if (v.has_value())
|
||||
return condition(new detail::not_condition_impl(condition(new detail::key_equals_condition_impl({ key.m_item_name, *v }))));
|
||||
else
|
||||
return condition(new detail::not_condition_impl(condition(new detail::key_is_empty_condition_impl(key.m_item_name))));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Operator to create a boolean opposite of the condition in @a rhs
|
||||
*/
|
||||
@@ -1146,7 +1350,7 @@ namespace literals
|
||||
* @param length The length of @a text
|
||||
* @return key The cif::key created
|
||||
*/
|
||||
inline key operator""_key(const char *text, size_t length)
|
||||
inline key operator""_key(const char *text, std::size_t length)
|
||||
{
|
||||
return key(std::string(text, length));
|
||||
}
|
||||
|
||||
@@ -98,19 +98,32 @@ class datablock : public std::list<category>
|
||||
m_name = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Attempt to load the dictionary specified in audit_conform category
|
||||
*
|
||||
*/
|
||||
void load_dictionary();
|
||||
|
||||
/**
|
||||
* @brief Load the dictionary named @a dict_name
|
||||
*
|
||||
* @param dict_name
|
||||
*/
|
||||
void load_dictionary(std::string_view dict_name);
|
||||
|
||||
/**
|
||||
* @brief Set the validator object to @a v
|
||||
*
|
||||
* @param v The new validator object, may be null
|
||||
*/
|
||||
void set_validator(const validator *v);
|
||||
void set_validator(const validator_base *v);
|
||||
|
||||
/**
|
||||
* @brief Get the validator object
|
||||
*
|
||||
* @return const validator* The validator or nullptr if there is none
|
||||
*/
|
||||
const validator *get_validator() const;
|
||||
const validator_base *get_validator() const;
|
||||
|
||||
/**
|
||||
* @brief Validates the content of this datablock and all its content
|
||||
@@ -231,7 +244,7 @@ class datablock : public std::list<category>
|
||||
|
||||
private:
|
||||
std::string m_name;
|
||||
const validator *m_validator = nullptr;
|
||||
const validator_base *m_validator = nullptr;
|
||||
};
|
||||
|
||||
} // namespace cif
|
||||
@@ -42,9 +42,4 @@ namespace cif
|
||||
*/
|
||||
validator parse_dictionary(std::string_view name, std::istream &is);
|
||||
|
||||
/**
|
||||
* @brief Extend the definitions in validator @a v with the contents of stream @a is
|
||||
*/
|
||||
void extend_dictionary(validator &v, std::istream &is);
|
||||
|
||||
} // namespace cif
|
||||
|
||||
@@ -85,11 +85,11 @@ class file : public std::list<datablock>
|
||||
* @param data The pointer to the character string with data to load
|
||||
* @param length The length of the data
|
||||
*/
|
||||
explicit file(const char *data, size_t length)
|
||||
explicit file(const char *data, std::size_t length)
|
||||
{
|
||||
struct membuf : public std::streambuf
|
||||
{
|
||||
membuf(char *text, size_t length)
|
||||
membuf(char *text, std::size_t length)
|
||||
{
|
||||
this->setg(text, text, text + length);
|
||||
}
|
||||
@@ -118,19 +118,6 @@ class file : public std::list<datablock>
|
||||
|
||||
/** @endcond */
|
||||
|
||||
/**
|
||||
* @brief Set the validator object to @a v
|
||||
*/
|
||||
void set_validator(const validator *v);
|
||||
|
||||
/**
|
||||
* @brief Get the validator object
|
||||
*/
|
||||
const validator *get_validator() const
|
||||
{
|
||||
return m_validator;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Validate the content and return true if everything was valid.
|
||||
*
|
||||
@@ -165,21 +152,6 @@ class file : public std::list<datablock>
|
||||
*/
|
||||
bool validate_links() const;
|
||||
|
||||
/**
|
||||
* @brief Attempt to load a dictionary (validator) based on
|
||||
* the contents of the *audit_conform* category, if available.
|
||||
*/
|
||||
void load_dictionary();
|
||||
|
||||
|
||||
/**
|
||||
* @brief Attempt to load the named dictionary @a name and
|
||||
* create a validator based on it.
|
||||
*
|
||||
* @param name The name of the dictionary to load
|
||||
*/
|
||||
void load_dictionary(std::string_view name);
|
||||
|
||||
/**
|
||||
* @brief Return true if a datablock with the name @a name is part of this file
|
||||
*/
|
||||
@@ -232,6 +204,18 @@ class file : public std::list<datablock>
|
||||
/** Load the data from @a is */
|
||||
void load(std::istream &is);
|
||||
|
||||
/** Load the data from the file specified by @a p using validator @a v */
|
||||
void load(const std::filesystem::path &p, const validator_base &v);
|
||||
|
||||
/** Load the data from @a is using validator @a v */
|
||||
void load(std::istream &is, const validator_base &v);
|
||||
|
||||
/** Load the data from the file specified by @a p using a validator constructed from dictionary @a dict */
|
||||
void load(const std::filesystem::path &p, std::string_view dict);
|
||||
|
||||
/** Load the data from @a is using a validator constructed from dictionary @a dict */
|
||||
void load(std::istream &is, std::string_view dict);
|
||||
|
||||
/** Save the data to the file specified by @a p */
|
||||
void save(const std::filesystem::path &p) const;
|
||||
|
||||
@@ -246,9 +230,6 @@ class file : public std::list<datablock>
|
||||
f.save(os);
|
||||
return os;
|
||||
}
|
||||
|
||||
private:
|
||||
const validator *m_validator = nullptr;
|
||||
};
|
||||
|
||||
} // namespace cif
|
||||
@@ -125,7 +125,7 @@ class format_plus_arg
|
||||
|
||||
private:
|
||||
|
||||
template <size_t... I>
|
||||
template <std::size_t... I>
|
||||
void copy_vargs(std::index_sequence<I...>)
|
||||
{
|
||||
((std::get<I>(m_vargs) = *std::get<I>(m_args)), ...);
|
||||
|
||||
@@ -36,7 +36,7 @@ namespace cif::gzio
|
||||
{
|
||||
|
||||
/** The default buffer size to use */
|
||||
const size_t kDefaultBufferSize = 256;
|
||||
const std::size_t kDefaultBufferSize = 256;
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
@@ -112,7 +112,7 @@ class basic_streambuf : public std::basic_streambuf<CharT, Traits>
|
||||
/// This implementation of streambuf can decompress (inflate) data compressed
|
||||
/// using zlib.
|
||||
|
||||
template <typename CharT, typename Traits, size_t BufferSize = kDefaultBufferSize>
|
||||
template <typename CharT, typename Traits, std::size_t BufferSize = kDefaultBufferSize>
|
||||
class basic_igzip_streambuf : public basic_streambuf<CharT, Traits>
|
||||
{
|
||||
public:
|
||||
@@ -317,7 +317,7 @@ class basic_igzip_streambuf : public basic_streambuf<CharT, Traits>
|
||||
///
|
||||
/// This implementation of streambuf can compress (deflate) data using zlib.
|
||||
|
||||
template <typename CharT, typename Traits, size_t BufferSize = kDefaultBufferSize>
|
||||
template <typename CharT, typename Traits, std::size_t BufferSize = kDefaultBufferSize>
|
||||
class basic_ogzip_streambuf : public basic_streambuf<CharT, Traits>
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -238,10 +238,10 @@ class item
|
||||
bool is_unknown() const { return m_value == "?"; }
|
||||
|
||||
/// \brief the length of the value string
|
||||
size_t length() const { return m_value.length(); }
|
||||
std::size_t length() const { return m_value.length(); }
|
||||
|
||||
/// \brief support for structured binding
|
||||
template <size_t N>
|
||||
template <std::size_t N>
|
||||
decltype(auto) get() const
|
||||
{
|
||||
if constexpr (N == 0)
|
||||
@@ -319,7 +319,7 @@ struct item_value
|
||||
return m_length != 0;
|
||||
}
|
||||
|
||||
size_t m_length = 0; ///< Length of the data
|
||||
std::size_t m_length = 0; ///< Length of the data
|
||||
union
|
||||
{
|
||||
char m_local_data[8]; ///< Storage area for small strings (strings smaller than kBufferSize)
|
||||
@@ -328,7 +328,7 @@ struct item_value
|
||||
};
|
||||
|
||||
/** The maximum length of locally stored strings */
|
||||
static constexpr size_t kBufferSize = sizeof(m_local_data);
|
||||
static constexpr std::size_t kBufferSize = sizeof(m_local_data);
|
||||
|
||||
// By using std::string_view instead of c_str we obain a
|
||||
// nice performance gain since we avoid many calls to strlen.
|
||||
@@ -378,7 +378,7 @@ struct item_handle
|
||||
template <typename T>
|
||||
item_handle &operator=(T &&value)
|
||||
{
|
||||
assign_value(item{ "", std::move(value) }.value());
|
||||
assign_value(item{ "", std::forward<T>(value) }.value());
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -389,7 +389,7 @@ struct item_handle
|
||||
* @param value The value
|
||||
* @return reference to this item_handle
|
||||
*/
|
||||
template <size_t N>
|
||||
template <std::size_t N>
|
||||
item_handle &operator=(const char (&value)[N])
|
||||
{
|
||||
assign_value(item{ "", std::move(value) }.value());
|
||||
@@ -608,6 +608,8 @@ struct item_handle::item_value_as<T, std::enable_if_t<std::is_arithmetic_v<T> an
|
||||
}
|
||||
result = 1;
|
||||
}
|
||||
else if (std::abs(v - value) <= std::numeric_limits<value_type>::epsilon())
|
||||
result = 0;
|
||||
else if (v < value)
|
||||
result = -1;
|
||||
else if (v > value)
|
||||
@@ -662,7 +664,7 @@ struct item_handle::item_value_as<T, std::enable_if_t<std::is_same_v<T, bool>>>
|
||||
}
|
||||
};
|
||||
|
||||
template <size_t N>
|
||||
template <std::size_t N>
|
||||
struct item_handle::item_value_as<char[N]>
|
||||
{
|
||||
static std::string convert(const item_handle &ref)
|
||||
|
||||
@@ -67,7 +67,7 @@ class iterator_impl
|
||||
/** @endcond */
|
||||
|
||||
/** variable that contains the number of elements in the tuple */
|
||||
static constexpr size_t N = sizeof...(Ts);
|
||||
static constexpr std::size_t N = sizeof...(Ts);
|
||||
|
||||
/** @cond */
|
||||
using category_type = std::remove_cv_t<Category>;
|
||||
@@ -176,7 +176,7 @@ class iterator_impl
|
||||
/** @endcond */
|
||||
|
||||
private:
|
||||
template <size_t... Is>
|
||||
template <std::size_t... Is>
|
||||
tuple_type get(std::index_sequence<Is...>) const
|
||||
{
|
||||
return m_current ? tuple_type{ m_current[m_item_ix[Is]].template as<Ts>()... } : tuple_type{};
|
||||
@@ -450,7 +450,7 @@ class iterator_proxy
|
||||
{
|
||||
public:
|
||||
/** @cond */
|
||||
static constexpr const size_t N = sizeof...(Ts);
|
||||
static constexpr const std::size_t N = sizeof...(Ts);
|
||||
|
||||
using category_type = Category;
|
||||
using row_type = std::conditional_t<std::is_const_v<category_type>, const row, row>;
|
||||
@@ -473,7 +473,7 @@ class iterator_proxy
|
||||
|
||||
bool empty() const { return m_begin == m_end; } ///< Return true if the range is empty
|
||||
explicit operator bool() const { return not empty(); } ///< Easy way to detect if the range is empty
|
||||
size_t size() const { return std::distance(begin(), end()); } ///< Return size of the range
|
||||
std::size_t size() const { return std::distance(begin(), end()); } ///< Return size of the range
|
||||
|
||||
// row front() { return *begin(); }
|
||||
// row back() { return *(std::prev(end())); }
|
||||
@@ -512,7 +512,7 @@ class conditional_iterator_proxy
|
||||
{
|
||||
public:
|
||||
/** @cond */
|
||||
static constexpr const size_t N = sizeof...(Ts);
|
||||
static constexpr const std::size_t N = sizeof...(Ts);
|
||||
|
||||
using category_type = std::remove_cv_t<CategoryType>;
|
||||
|
||||
@@ -606,7 +606,7 @@ class conditional_iterator_proxy
|
||||
|
||||
bool empty() const; ///< Return true if the range is empty
|
||||
explicit operator bool() const { return not empty(); } ///< Easy way to detect if the range is empty
|
||||
size_t size() const { return std::distance(begin(), end()); } ///< Return size of the range
|
||||
std::size_t size() const { return std::distance(begin(), end()); } ///< Return size of the range
|
||||
|
||||
row_handle front() { return *begin(); } ///< Return reference to the first row
|
||||
// row_handle back() { return *begin(); }
|
||||
|
||||
@@ -59,27 +59,27 @@ template <typename M>
|
||||
class matrix_expression
|
||||
{
|
||||
public:
|
||||
constexpr size_t dim_m() const { return static_cast<const M &>(*this).dim_m(); } ///< Return the size (dimension) in direction m
|
||||
constexpr size_t dim_n() const { return static_cast<const M &>(*this).dim_n(); } ///< Return the size (dimension) in direction n
|
||||
constexpr std::size_t dim_m() const { return static_cast<const M &>(*this).dim_m(); } ///< Return the size (dimension) in direction m
|
||||
constexpr std::size_t dim_n() const { return static_cast<const M &>(*this).dim_n(); } ///< Return the size (dimension) in direction n
|
||||
|
||||
constexpr bool empty() const { return dim_m() == 0 or dim_n() == 0; } ///< Convenient way to test for empty matrices
|
||||
|
||||
/** Return a reference to element [ @a i, @a j ] */
|
||||
constexpr auto &operator()(size_t i, size_t j)
|
||||
constexpr auto &operator()(std::size_t i, std::size_t j)
|
||||
{
|
||||
return static_cast<M &>(*this).operator()(i, j);
|
||||
}
|
||||
|
||||
/** Return the value of element [ @a i, @a j ] */
|
||||
constexpr auto operator()(size_t i, size_t j) const
|
||||
constexpr auto operator()(std::size_t i, std::size_t j) const
|
||||
{
|
||||
return static_cast<const M &>(*this).operator()(i, j);
|
||||
}
|
||||
|
||||
/** Swap the contents of rows @a r1 and @a r2 */
|
||||
void swap_row(size_t r1, size_t r2)
|
||||
void swap_row(std::size_t r1, std::size_t r2)
|
||||
{
|
||||
for (size_t c = 0; c < dim_m(); ++c)
|
||||
for (std::size_t c = 0; c < dim_m(); ++c)
|
||||
{
|
||||
auto v = operator()(r1, c);
|
||||
operator()(r1, c) = operator()(r2, c);
|
||||
@@ -88,9 +88,9 @@ class matrix_expression
|
||||
}
|
||||
|
||||
/** Swap the contents of columns @a c1 and @a c2 */
|
||||
void swap_col(size_t c1, size_t c2)
|
||||
void swap_col(std::size_t c1, std::size_t c2)
|
||||
{
|
||||
for (size_t r = 0; r < dim_n(); ++r)
|
||||
for (std::size_t r = 0; r < dim_n(); ++r)
|
||||
{
|
||||
auto &a = operator()(r, c1);
|
||||
auto &b = operator()(r, c2);
|
||||
@@ -103,11 +103,11 @@ class matrix_expression
|
||||
{
|
||||
os << '[';
|
||||
|
||||
for (size_t i = 0; i < m.dim_m(); ++i)
|
||||
for (std::size_t i = 0; i < m.dim_m(); ++i)
|
||||
{
|
||||
os << '[';
|
||||
|
||||
for (size_t j = 0; j < m.dim_n(); ++j)
|
||||
for (std::size_t j = 0; j < m.dim_n(); ++j)
|
||||
{
|
||||
os << m(i, j);
|
||||
if (j + 1 < m.dim_n())
|
||||
@@ -156,9 +156,9 @@ class matrix : public matrix_expression<matrix<F>>
|
||||
, m_n(m.dim_n())
|
||||
, m_data(m_m * m_n)
|
||||
{
|
||||
for (size_t i = 0; i < m_m; ++i)
|
||||
for (std::size_t i = 0; i < m_m; ++i)
|
||||
{
|
||||
for (size_t j = 0; j < m_n; ++j)
|
||||
for (std::size_t j = 0; j < m_n; ++j)
|
||||
operator()(i, j) = m(i, j);
|
||||
}
|
||||
}
|
||||
@@ -171,7 +171,7 @@ class matrix : public matrix_expression<matrix<F>>
|
||||
* @param n Requested dimension N
|
||||
* @param v Value to store in each element
|
||||
*/
|
||||
matrix(size_t m, size_t n, value_type v = 0)
|
||||
matrix(std::size_t m, std::size_t n, value_type v = 0)
|
||||
: m_m(m)
|
||||
, m_n(n)
|
||||
, m_data(m_m * m_n)
|
||||
@@ -187,11 +187,11 @@ class matrix : public matrix_expression<matrix<F>>
|
||||
matrix &operator=(const matrix &m) = default;
|
||||
/** @endcond */
|
||||
|
||||
constexpr size_t dim_m() const { return m_m; } ///< Return dimension m
|
||||
constexpr size_t dim_n() const { return m_n; } ///< Return dimension n
|
||||
constexpr std::size_t dim_m() const { return m_m; } ///< Return dimension m
|
||||
constexpr std::size_t dim_n() const { return m_n; } ///< Return dimension n
|
||||
|
||||
/** Return the value of element [ @a i, @a j ] */
|
||||
constexpr value_type operator()(size_t i, size_t j) const
|
||||
constexpr value_type operator()(std::size_t i, std::size_t j) const
|
||||
{
|
||||
assert(i < m_m);
|
||||
assert(j < m_n);
|
||||
@@ -199,7 +199,7 @@ class matrix : public matrix_expression<matrix<F>>
|
||||
}
|
||||
|
||||
/** Return a reference to element [ @a i, @a j ] */
|
||||
constexpr value_type &operator()(size_t i, size_t j)
|
||||
constexpr value_type &operator()(std::size_t i, std::size_t j)
|
||||
{
|
||||
assert(i < m_m);
|
||||
assert(j < m_n);
|
||||
@@ -207,7 +207,7 @@ class matrix : public matrix_expression<matrix<F>>
|
||||
}
|
||||
|
||||
private:
|
||||
size_t m_m = 0, m_n = 0;
|
||||
std::size_t m_m = 0, m_n = 0;
|
||||
std::vector<value_type> m_data;
|
||||
};
|
||||
|
||||
@@ -224,7 +224,7 @@ class matrix : public matrix_expression<matrix<F>>
|
||||
* element m i,j is mapped to [i * n + j] and thus storage is row major
|
||||
*/
|
||||
|
||||
template <typename F, size_t M, size_t N>
|
||||
template <typename F, std::size_t M, std::size_t N>
|
||||
class matrix_fixed : public matrix_expression<matrix_fixed<F, M, N>>
|
||||
{
|
||||
public:
|
||||
@@ -232,16 +232,16 @@ class matrix_fixed : public matrix_expression<matrix_fixed<F, M, N>>
|
||||
using value_type = F;
|
||||
|
||||
/** The storage size */
|
||||
static constexpr size_t kSize = M * N;
|
||||
static constexpr std::size_t kSize = M * N;
|
||||
|
||||
/** Copy constructor */
|
||||
template <typename M2>
|
||||
matrix_fixed(const M2 &m)
|
||||
{
|
||||
assert(M == m.dim_m() and N == m.dim_n());
|
||||
for (size_t i = 0; i < M; ++i)
|
||||
for (std::size_t i = 0; i < M; ++i)
|
||||
{
|
||||
for (size_t j = 0; j < N; ++j)
|
||||
for (std::size_t j = 0; j < N; ++j)
|
||||
operator()(i, j) = m(i, j);
|
||||
}
|
||||
}
|
||||
@@ -266,18 +266,18 @@ class matrix_fixed : public matrix_expression<matrix_fixed<F, M, N>>
|
||||
/** @endcond */
|
||||
|
||||
/** Store the values in @a a in the matrix */
|
||||
template<size_t... Ixs>
|
||||
template<std::size_t... Ixs>
|
||||
matrix_fixed& fill(const F (&a)[kSize], std::index_sequence<Ixs...>)
|
||||
{
|
||||
m_data = { a[Ixs]... };
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr size_t dim_m() const { return M; } ///< Return dimension m
|
||||
constexpr size_t dim_n() const { return N; } ///< Return dimension n
|
||||
constexpr std::size_t dim_m() const { return M; } ///< Return dimension m
|
||||
constexpr std::size_t dim_n() const { return N; } ///< Return dimension n
|
||||
|
||||
/** Return the value of element [ @a i, @a j ] */
|
||||
constexpr value_type operator()(size_t i, size_t j) const
|
||||
constexpr value_type operator()(std::size_t i, std::size_t j) const
|
||||
{
|
||||
assert(i < M);
|
||||
assert(j < N);
|
||||
@@ -285,7 +285,7 @@ class matrix_fixed : public matrix_expression<matrix_fixed<F, M, N>>
|
||||
}
|
||||
|
||||
/** Return a reference to element [ @a i, @a j ] */
|
||||
constexpr value_type &operator()(size_t i, size_t j)
|
||||
constexpr value_type &operator()(std::size_t i, std::size_t j)
|
||||
{
|
||||
assert(i < M);
|
||||
assert(j < N);
|
||||
@@ -322,7 +322,7 @@ class symmetric_matrix : public matrix_expression<symmetric_matrix<F>>
|
||||
using value_type = F;
|
||||
|
||||
/** constructor for a matrix of size @a n x @a n elements with value @a v */
|
||||
symmetric_matrix(size_t n, value_type v = 0)
|
||||
symmetric_matrix(std::size_t n, value_type v = 0)
|
||||
: m_n(n)
|
||||
, m_data((m_n * (m_n + 1)) / 2)
|
||||
{
|
||||
@@ -337,11 +337,11 @@ class symmetric_matrix : public matrix_expression<symmetric_matrix<F>>
|
||||
symmetric_matrix &operator=(const symmetric_matrix &m) = default;
|
||||
/** @endcond */
|
||||
|
||||
constexpr size_t dim_m() const { return m_n; } ///< Return dimension m
|
||||
constexpr size_t dim_n() const { return m_n; } ///< Return dimension n
|
||||
constexpr std::size_t dim_m() const { return m_n; } ///< Return dimension m
|
||||
constexpr std::size_t dim_n() const { return m_n; } ///< Return dimension n
|
||||
|
||||
/** Return the value of element [ @a i, @a j ] */
|
||||
constexpr value_type operator()(size_t i, size_t j) const
|
||||
constexpr value_type operator()(std::size_t i, std::size_t j) const
|
||||
{
|
||||
return i < j
|
||||
? m_data[(j * (j + 1)) / 2 + i]
|
||||
@@ -349,7 +349,7 @@ class symmetric_matrix : public matrix_expression<symmetric_matrix<F>>
|
||||
}
|
||||
|
||||
/** Return a reference to element [ @a i, @a j ] */
|
||||
constexpr value_type &operator()(size_t i, size_t j)
|
||||
constexpr value_type &operator()(std::size_t i, std::size_t j)
|
||||
{
|
||||
if (i > j)
|
||||
std::swap(i, j);
|
||||
@@ -358,7 +358,7 @@ class symmetric_matrix : public matrix_expression<symmetric_matrix<F>>
|
||||
}
|
||||
|
||||
private:
|
||||
size_t m_n;
|
||||
std::size_t m_n;
|
||||
std::vector<value_type> m_data;
|
||||
};
|
||||
|
||||
@@ -373,7 +373,7 @@ class symmetric_matrix : public matrix_expression<symmetric_matrix<F>>
|
||||
* matrix is m x n, addressing i,j is 0 <= i < m and 0 <= j < n
|
||||
* element m i,j is mapped to [i * n + j] and thus storage is row major
|
||||
*/
|
||||
template <typename F, size_t M>
|
||||
template <typename F, std::size_t M>
|
||||
class symmetric_matrix_fixed : public matrix_expression<symmetric_matrix_fixed<F, M>>
|
||||
{
|
||||
public:
|
||||
@@ -393,11 +393,11 @@ class symmetric_matrix_fixed : public matrix_expression<symmetric_matrix_fixed<F
|
||||
symmetric_matrix_fixed &operator=(const symmetric_matrix_fixed &m) = default;
|
||||
/** @endcond */
|
||||
|
||||
constexpr size_t dim_m() const { return M; } ///< Return dimension m
|
||||
constexpr size_t dim_n() const { return M; } ///< Return dimension n
|
||||
constexpr std::size_t dim_m() const { return M; } ///< Return dimension m
|
||||
constexpr std::size_t dim_n() const { return M; } ///< Return dimension n
|
||||
|
||||
/** Return the value of element [ @a i, @a j ] */
|
||||
constexpr value_type operator()(size_t i, size_t j) const
|
||||
constexpr value_type operator()(std::size_t i, std::size_t j) const
|
||||
{
|
||||
return i < j
|
||||
? m_data[(j * (j + 1)) / 2 + i]
|
||||
@@ -405,7 +405,7 @@ class symmetric_matrix_fixed : public matrix_expression<symmetric_matrix_fixed<F
|
||||
}
|
||||
|
||||
/** Return a reference to element [ @a i, @a j ] */
|
||||
constexpr value_type &operator()(size_t i, size_t j)
|
||||
constexpr value_type &operator()(std::size_t i, std::size_t j)
|
||||
{
|
||||
if (i > j)
|
||||
std::swap(i, j);
|
||||
@@ -444,22 +444,22 @@ class identity_matrix : public matrix_expression<identity_matrix<F>>
|
||||
using value_type = F;
|
||||
|
||||
/** constructor taking a dimension @a n */
|
||||
identity_matrix(size_t n)
|
||||
identity_matrix(std::size_t n)
|
||||
: m_n(n)
|
||||
{
|
||||
}
|
||||
|
||||
constexpr size_t dim_m() const { return m_n; } ///< Return dimension m
|
||||
constexpr size_t dim_n() const { return m_n; } ///< Return dimension n
|
||||
constexpr std::size_t dim_m() const { return m_n; } ///< Return dimension m
|
||||
constexpr std::size_t dim_n() const { return m_n; } ///< Return dimension n
|
||||
|
||||
/** Return the value of element [ @a i, @a j ] */
|
||||
constexpr value_type operator()(size_t i, size_t j) const
|
||||
constexpr value_type operator()(std::size_t i, std::size_t j) const
|
||||
{
|
||||
return static_cast<value_type>(i == j ? 1 : 0);
|
||||
}
|
||||
|
||||
private:
|
||||
size_t m_n;
|
||||
std::size_t m_n;
|
||||
};
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
@@ -484,11 +484,11 @@ class matrix_subtraction : public matrix_expression<matrix_subtraction<M1, M2>>
|
||||
assert(m_m1.dim_n() == m_m2.dim_n());
|
||||
}
|
||||
|
||||
constexpr size_t dim_m() const { return m_m1.dim_m(); } ///< Return dimension m
|
||||
constexpr size_t dim_n() const { return m_m1.dim_n(); } ///< Return dimension n
|
||||
constexpr std::size_t dim_m() const { return m_m1.dim_m(); } ///< Return dimension m
|
||||
constexpr std::size_t dim_n() const { return m_m1.dim_n(); } ///< Return dimension n
|
||||
|
||||
/** Access to the value of element [ @a i, @a j ] */
|
||||
constexpr auto operator()(size_t i, size_t j) const
|
||||
constexpr auto operator()(std::size_t i, std::size_t j) const
|
||||
{
|
||||
return m_m1(i, j) - m_m2(i, j);
|
||||
}
|
||||
@@ -523,17 +523,17 @@ class matrix_matrix_multiplication : public matrix_expression<matrix_matrix_mult
|
||||
assert(m1.dim_m() == m2.dim_n());
|
||||
}
|
||||
|
||||
constexpr size_t dim_m() const { return m_m1.dim_m(); } ///< Return dimension m
|
||||
constexpr size_t dim_n() const { return m_m1.dim_n(); } ///< Return dimension n
|
||||
constexpr std::size_t dim_m() const { return m_m1.dim_m(); } ///< Return dimension m
|
||||
constexpr std::size_t dim_n() const { return m_m1.dim_n(); } ///< Return dimension n
|
||||
|
||||
/** Access to the value of element [ @a i, @a j ] */
|
||||
constexpr auto operator()(size_t i, size_t j) const
|
||||
constexpr auto operator()(std::size_t i, std::size_t j) const
|
||||
{
|
||||
using value_type = decltype(m_m1(0, 0));
|
||||
|
||||
value_type result = {};
|
||||
|
||||
for (size_t k = 0; k < m_m1.dim_m(); ++k)
|
||||
for (std::size_t k = 0; k < m_m1.dim_m(); ++k)
|
||||
result += m_m1(i, k) * m_m2(k, j);
|
||||
|
||||
return result;
|
||||
@@ -564,11 +564,11 @@ class matrix_scalar_multiplication : public matrix_expression<matrix_scalar_mult
|
||||
{
|
||||
}
|
||||
|
||||
constexpr size_t dim_m() const { return m_m.dim_m(); } ///< Return dimension m
|
||||
constexpr size_t dim_n() const { return m_m.dim_n(); } ///< Return dimension n
|
||||
constexpr std::size_t dim_m() const { return m_m.dim_m(); } ///< Return dimension m
|
||||
constexpr std::size_t dim_n() const { return m_m.dim_n(); } ///< Return dimension n
|
||||
|
||||
/** Access to the value of element [ @a i, @a j ] */
|
||||
constexpr auto operator()(size_t i, size_t j) const
|
||||
constexpr auto operator()(std::size_t i, std::size_t j) const
|
||||
{
|
||||
return m_m(i, j) * m_v;
|
||||
}
|
||||
@@ -655,21 +655,21 @@ class matrix_cofactors : public matrix_expression<matrix_cofactors<M>>
|
||||
{
|
||||
}
|
||||
|
||||
constexpr size_t dim_m() const { return m_m.dim_m(); } ///< Return dimension m
|
||||
constexpr size_t dim_n() const { return m_m.dim_n(); } ///< Return dimension n
|
||||
constexpr std::size_t dim_m() const { return m_m.dim_m(); } ///< Return dimension m
|
||||
constexpr std::size_t dim_n() const { return m_m.dim_n(); } ///< Return dimension n
|
||||
|
||||
/** Access to the value of element [ @a i, @a j ] */
|
||||
constexpr auto operator()(size_t i, size_t j) const
|
||||
constexpr auto operator()(std::size_t i, std::size_t j) const
|
||||
{
|
||||
const size_t ixs[4][3] = {
|
||||
const std::size_t ixs[4][3] = {
|
||||
{ 1, 2, 3 },
|
||||
{ 0, 2, 3 },
|
||||
{ 0, 1, 3 },
|
||||
{ 0, 1, 2 }
|
||||
};
|
||||
|
||||
const size_t *ix = ixs[i];
|
||||
const size_t *iy = ixs[j];
|
||||
const std::size_t *ix = ixs[i];
|
||||
const std::size_t *iy = ixs[j];
|
||||
|
||||
auto result =
|
||||
m_m(ix[0], iy[0]) * m_m(ix[1], iy[1]) * m_m(ix[2], iy[2]) +
|
||||
|
||||
@@ -350,7 +350,12 @@ class atom
|
||||
std::string get_pdb_ins_code() const { return get_property("pdbx_PDB_ins_code"); } ///< Return the pdb_ins_code property
|
||||
|
||||
/// Return true if this atom is an alternate
|
||||
bool is_alternate() const { return not get_label_alt_id().empty(); }
|
||||
bool is_alternate() const
|
||||
{
|
||||
if (auto alt_id = get_label_alt_id(); alt_id.empty() or alt_id == ".")
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Convenience method to return a string that might be ID in PDB space
|
||||
std::string pdb_id() const
|
||||
@@ -550,6 +555,9 @@ class residue
|
||||
/// \brief Return true if this residue has alternate atoms
|
||||
bool has_alternate_atoms() const;
|
||||
|
||||
/// \brief Return true if this residue has alternate atoms for the atom \a atomID
|
||||
bool has_alternate_atoms_for(const std::string &atomID) const;
|
||||
|
||||
/// \brief Return the list of unique alt ID's present in this residue
|
||||
std::set<std::string> get_alternate_ids() const;
|
||||
|
||||
@@ -572,6 +580,10 @@ class residue
|
||||
m_auth_seq_id == rhs.m_auth_seq_id);
|
||||
}
|
||||
|
||||
/// @brief Create a new atom and add it to the list
|
||||
/// @return newly created atom
|
||||
virtual atom create_new_atom(atom_type inType, const std::string &inAtomID, point inLocation);
|
||||
|
||||
protected:
|
||||
/** @cond */
|
||||
residue() {}
|
||||
@@ -604,7 +616,7 @@ class monomer : public residue
|
||||
monomer &operator=(monomer &&rhs);
|
||||
|
||||
/// \brief constructor with actual values
|
||||
monomer(const polymer &polymer, size_t index, int seqID, const std::string &authSeqID,
|
||||
monomer(const polymer &polymer, std::size_t index, int seqID, const std::string &authSeqID,
|
||||
const std::string &pdbInsCode, const std::string &compoundID);
|
||||
|
||||
bool is_first_in_chain() const; ///< Return if this residue is the first residue in the chain
|
||||
@@ -624,8 +636,8 @@ class monomer : public residue
|
||||
float omega() const; ///< Return the omega value for this residue
|
||||
|
||||
// torsion angles
|
||||
size_t nr_of_chis() const; ///< Return how many torsion angles can be calculated
|
||||
float chi(size_t i) const; ///< Return torsion angle @a i
|
||||
std::size_t nr_of_chis() const; ///< Return how many torsion angles can be calculated
|
||||
float chi(std::size_t i) const; ///< Return torsion angle @a i
|
||||
|
||||
bool is_cis() const; ///< Return true if this residue is in a cis conformation
|
||||
|
||||
@@ -672,9 +684,11 @@ class monomer : public residue
|
||||
return m_polymer == rhs.m_polymer and m_index == rhs.m_index;
|
||||
}
|
||||
|
||||
atom create_new_atom(atom_type inType, const std::string &inAtomID, point inLocation) override;
|
||||
|
||||
private:
|
||||
const polymer *m_polymer;
|
||||
size_t m_index;
|
||||
std::size_t m_index;
|
||||
};
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
@@ -756,9 +770,9 @@ class sugar : public residue
|
||||
void set_link(atom link) { m_link = link; }
|
||||
|
||||
/// \brief Return the sugar number of the sugar linked to C1
|
||||
size_t get_link_nr() const
|
||||
std::size_t get_link_nr() const
|
||||
{
|
||||
size_t result = 0;
|
||||
std::size_t result = 0;
|
||||
if (m_link)
|
||||
result = m_link.get_property_int("auth_seq_id");
|
||||
return result;
|
||||
@@ -865,10 +879,10 @@ class structure
|
||||
{
|
||||
public:
|
||||
/// \brief Read the structure from cif::file @a p
|
||||
structure(file &p, size_t modelNr = 1, StructureOpenOptions options = {});
|
||||
structure(file &p, std::size_t modelNr = 1, StructureOpenOptions options = {});
|
||||
|
||||
/// \brief Load the structure from already parsed mmCIF data in @a db
|
||||
structure(datablock &db, size_t modelNr = 1, StructureOpenOptions options = {});
|
||||
structure(datablock &db, std::size_t modelNr = 1, StructureOpenOptions options = {});
|
||||
|
||||
/** @cond */
|
||||
structure(structure &&s) = default;
|
||||
@@ -881,7 +895,7 @@ class structure
|
||||
~structure() = default;
|
||||
|
||||
/// \brief Return the model number
|
||||
size_t get_model_nr() const { return m_model_nr; }
|
||||
std::size_t get_model_nr() const { return m_model_nr; }
|
||||
|
||||
/// \brief Return a list of all the atoms in this structure
|
||||
const std::vector<atom> &atoms() const { return m_atoms; }
|
||||
@@ -1091,6 +1105,9 @@ class structure
|
||||
/// \brief emplace the moved atom @a atom
|
||||
atom &emplace_atom(atom &&atom);
|
||||
|
||||
/// \brief Reorder atom_site atoms based on 'natural' ordering
|
||||
void reorder_atoms();
|
||||
|
||||
private:
|
||||
friend polymer;
|
||||
friend residue;
|
||||
@@ -1107,9 +1124,9 @@ class structure
|
||||
void remove_sugar(sugar &sugar);
|
||||
|
||||
datablock &m_db;
|
||||
size_t m_model_nr;
|
||||
std::size_t m_model_nr;
|
||||
std::vector<atom> m_atoms;
|
||||
std::vector<size_t> m_atom_index;
|
||||
std::vector<std::size_t> m_atom_index;
|
||||
std::list<polymer> m_polymers;
|
||||
std::list<branch> m_branches;
|
||||
std::vector<residue> m_non_polymers;
|
||||
|
||||
@@ -39,6 +39,8 @@
|
||||
namespace cif
|
||||
{
|
||||
|
||||
class validator_base;
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
/** Exception that is thrown when the mmCIF file contains a parsing error */
|
||||
@@ -73,7 +75,15 @@ class sac_parser
|
||||
{
|
||||
public:
|
||||
/** @cond */
|
||||
using datablock_index = std::map<std::string, std::size_t>;
|
||||
struct iless_op
|
||||
{
|
||||
bool operator()(std::string_view a, std::string_view b) const
|
||||
{
|
||||
return icompare(a, b) < 0;
|
||||
}
|
||||
};
|
||||
|
||||
using datablock_index = std::map<std::string, std::size_t, iless_op>;
|
||||
|
||||
virtual ~sac_parser() = default;
|
||||
/** @endcond */
|
||||
@@ -299,6 +309,14 @@ class sac_parser
|
||||
class parser : public sac_parser
|
||||
{
|
||||
public:
|
||||
/// \brief constructor, generates data into @a file from @a is using validator @a v
|
||||
parser(std::istream &is, file &file, const validator_base *v)
|
||||
: sac_parser(is)
|
||||
, m_file(file)
|
||||
, m_validator(v)
|
||||
{
|
||||
}
|
||||
|
||||
/// \brief constructor, generates data into @a file from @a is
|
||||
parser(std::istream &is, file &file)
|
||||
: sac_parser(is)
|
||||
@@ -319,6 +337,7 @@ class parser : public sac_parser
|
||||
file &m_file;
|
||||
datablock *m_datablock = nullptr;
|
||||
category *m_category = nullptr;
|
||||
const validator_base *m_validator = nullptr;
|
||||
row_handle m_row;
|
||||
|
||||
/** @endcond */
|
||||
|
||||
@@ -662,12 +662,23 @@ struct point_type
|
||||
return std::make_tuple(std::ref(m_x), std::ref(m_y), std::ref(m_z));
|
||||
}
|
||||
|
||||
/// \brief Compare with @a rhs
|
||||
#if defined(__cpp_impl_three_way_comparison)
|
||||
/// \brief a default spaceship operator
|
||||
constexpr auto operator<=>(const point_type &rhs) const = default;
|
||||
#else
|
||||
/// \brief a default equals operator
|
||||
constexpr bool operator==(const point_type &rhs) const
|
||||
{
|
||||
return m_x == rhs.m_x and m_y == rhs.m_y and m_z == rhs.m_z;
|
||||
}
|
||||
|
||||
/// \brief a default not-equals operator
|
||||
constexpr bool operator!=(const point_type &rhs) const
|
||||
{
|
||||
return not operator==(rhs);
|
||||
}
|
||||
#endif
|
||||
|
||||
// consider point as a vector... perhaps I should rename point?
|
||||
|
||||
/// \brief looking at the point as if it is a vector, return the squared length
|
||||
@@ -867,7 +878,7 @@ class spherical_dots
|
||||
}
|
||||
|
||||
/// \brief The number of points
|
||||
size_t size() const { return P; }
|
||||
std::size_t size() const { return P; }
|
||||
|
||||
/// \brief Access a point by index
|
||||
const point operator[](uint32_t inIx) const { return m_points[inIx]; }
|
||||
|
||||
@@ -85,7 +85,7 @@ namespace detail
|
||||
template <typename... C>
|
||||
struct get_row_result
|
||||
{
|
||||
static constexpr size_t N = sizeof...(C);
|
||||
static constexpr std::size_t N = sizeof...(C);
|
||||
|
||||
get_row_result(const row_handle &r, std::array<uint16_t, N> &&items)
|
||||
: m_row(r)
|
||||
@@ -104,7 +104,7 @@ namespace detail
|
||||
return get<Ts...>(std::index_sequence_for<Ts...>{});
|
||||
}
|
||||
|
||||
template <typename... Ts, size_t... Is>
|
||||
template <typename... Ts, std::size_t... Is>
|
||||
std::tuple<Ts...> get(std::index_sequence<Is...>) const
|
||||
{
|
||||
return std::tuple<Ts...>{ m_row[m_items[Is]].template as<Ts>()... };
|
||||
|
||||
@@ -300,7 +300,7 @@ namespace literals
|
||||
* @endcode
|
||||
*
|
||||
*/
|
||||
inline sym_op operator""_symop(const char *text, size_t length)
|
||||
inline sym_op operator""_symop(const char *text, std::size_t length)
|
||||
{
|
||||
return sym_op({ text, length });
|
||||
}
|
||||
@@ -464,7 +464,7 @@ class spacegroup : public std::vector<transformation>
|
||||
|
||||
private:
|
||||
int m_nr;
|
||||
size_t m_index;
|
||||
std::size_t m_index;
|
||||
};
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
@@ -352,7 +352,7 @@ std::string cif_id_for_number(int number);
|
||||
* a dynamic programming approach to get the most efficient filling of
|
||||
* the space.
|
||||
*/
|
||||
std::vector<std::string> word_wrap(const std::string &text, size_t width);
|
||||
std::vector<std::string> word_wrap(const std::string &text, std::size_t width);
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
/// \brief std::from_chars for floating point types.
|
||||
@@ -378,7 +378,7 @@ std::from_chars_result from_chars(const char *first, const char *last, FloatType
|
||||
} state = IntegerSign;
|
||||
int sign = 1;
|
||||
unsigned long long vi = 0;
|
||||
long double f = 1;
|
||||
int fl = 0, tz = 0;
|
||||
int exponent_sign = 1;
|
||||
int exponent = 0;
|
||||
bool done = false;
|
||||
@@ -427,7 +427,14 @@ std::from_chars_result from_chars(const char *first, const char *last, FloatType
|
||||
if (ch >= '0' and ch <= '9')
|
||||
{
|
||||
vi = 10 * vi + (ch - '0');
|
||||
f /= 10;
|
||||
|
||||
if (ch == '0')
|
||||
tz += 1;
|
||||
else
|
||||
{
|
||||
fl += tz + 1;
|
||||
tz = 0;
|
||||
}
|
||||
}
|
||||
else if (ch == 'e' or ch == 'E')
|
||||
state = ExponentSign;
|
||||
@@ -469,7 +476,10 @@ std::from_chars_result from_chars(const char *first, const char *last, FloatType
|
||||
|
||||
if (not (bool)result.ec)
|
||||
{
|
||||
long double v = f * vi * sign;
|
||||
while (tz-- > 0)
|
||||
vi /= 10;
|
||||
|
||||
long double v = std::pow(10, -fl) * vi * sign;
|
||||
if (exponent != 0)
|
||||
v *= std::pow(10, exponent * exponent_sign);
|
||||
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#include <filesystem>
|
||||
#include <list>
|
||||
#include <mutex>
|
||||
#include <optional>
|
||||
#include <system_error>
|
||||
#include <utility>
|
||||
|
||||
@@ -48,6 +49,7 @@
|
||||
namespace cif
|
||||
{
|
||||
|
||||
class category;
|
||||
struct category_validator;
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
@@ -384,57 +386,32 @@ struct link_validator
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* @brief The validator class combines all the link, category and item validator classes
|
||||
*
|
||||
*/
|
||||
class validator
|
||||
class validator_base
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Construct a new validator object
|
||||
*
|
||||
* @param name The name of the underlying dictionary
|
||||
*/
|
||||
validator(std::string_view name)
|
||||
: m_name(name)
|
||||
{
|
||||
}
|
||||
|
||||
/// @brief destructor
|
||||
~validator() = default;
|
||||
virtual ~validator_base() = default;
|
||||
|
||||
validator(const validator &rhs) = delete;
|
||||
validator &operator=(const validator &rhs) = delete;
|
||||
validator_base(const validator_base &rhs) = delete;
|
||||
validator_base &operator=(const validator_base &rhs) = delete;
|
||||
|
||||
/// @brief move constructor
|
||||
validator(validator &&rhs) = default;
|
||||
validator_base(validator_base &&rhs) = default;
|
||||
|
||||
/// @brief move assignment operator
|
||||
validator &operator=(validator &&rhs) = default;
|
||||
|
||||
friend class dictionary_parser;
|
||||
|
||||
/// @brief Add type_validator @a v to the list of type validators
|
||||
void add_type_validator(type_validator &&v);
|
||||
validator_base &operator=(validator_base &&rhs) = default;
|
||||
|
||||
/// @brief Return the type validator for @a type_code, may return nullptr
|
||||
const type_validator *get_validator_for_type(std::string_view type_code) const;
|
||||
|
||||
/// @brief Add category_validator @a v to the list of category validators
|
||||
void add_category_validator(category_validator &&v);
|
||||
virtual const type_validator *get_validator_for_type(std::string_view type_code) const = 0;
|
||||
|
||||
/// @brief Return the category validator for @a category, may return nullptr
|
||||
const category_validator *get_validator_for_category(std::string_view category) const;
|
||||
|
||||
/// @brief Add link_validator @a v to the list of link validators
|
||||
void add_link_validator(link_validator &&v);
|
||||
virtual const category_validator *get_validator_for_category(std::string_view category) const = 0;
|
||||
|
||||
/// @brief Return the list of link validators for which the parent is @a category
|
||||
std::vector<const link_validator *> get_links_for_parent(std::string_view category) const;
|
||||
virtual std::vector<const link_validator *> get_links_for_parent(std::string_view category) const = 0;
|
||||
|
||||
/// @brief Return the list of link validators for which the child is @a category
|
||||
std::vector<const link_validator *> get_links_for_child(std::string_view category) const;
|
||||
virtual std::vector<const link_validator *> get_links_for_child(std::string_view category) const = 0;
|
||||
|
||||
/// @brief Bottleneck function to report an error in validation
|
||||
void report_error(validation_error err, bool fatal = true) const
|
||||
@@ -456,19 +433,87 @@ class validator
|
||||
void report_error(std::error_code ec, std::string_view category,
|
||||
std::string_view item, bool fatal = true) const;
|
||||
|
||||
const std::string &name() const { return m_name; } ///< Get the name of this validator
|
||||
void set_name(const std::string &name) { m_name = name; } ///< Set the name of this validator
|
||||
const std::string &name() const { return m_name; } ///< Get the name of this validator
|
||||
const std::string &version() const { return m_version; } ///< Get the version of this validator
|
||||
bool is_strict() const { return m_strict; } ///< Get the strict flag of this validator
|
||||
|
||||
const std::string &version() const { return m_version; } ///< Get the version of this validator
|
||||
protected:
|
||||
/**
|
||||
* @brief Construct a new validator object
|
||||
*
|
||||
* @param name The name of the underlying dictionary
|
||||
*/
|
||||
validator_base(std::string_view name)
|
||||
: m_name(name)
|
||||
{
|
||||
}
|
||||
|
||||
validator_base() = default;
|
||||
|
||||
std::string m_name;
|
||||
std::string m_version;
|
||||
bool m_strict = false;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief The validator class combines all the link, category and item validator classes
|
||||
*
|
||||
*/
|
||||
class validator : public validator_base
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Construct a new validator object
|
||||
*
|
||||
* @param name The name of the underlying dictionary
|
||||
*/
|
||||
validator(std::string_view name)
|
||||
: validator_base(name)
|
||||
{
|
||||
}
|
||||
|
||||
/// @brief destructor
|
||||
~validator() = default;
|
||||
|
||||
validator(const validator &rhs) = delete;
|
||||
validator &operator=(const validator &rhs) = delete;
|
||||
|
||||
/// @brief move constructor
|
||||
validator(validator &&rhs) = default;
|
||||
|
||||
/// @brief move assignment operator
|
||||
validator &operator=(validator &&rhs) = default;
|
||||
|
||||
friend class dictionary_parser;
|
||||
|
||||
/// @brief Add type_validator @a v to the list of type validators
|
||||
void add_type_validator(type_validator &&v);
|
||||
|
||||
/// @brief Return the type validator for @a type_code, may return nullptr
|
||||
const type_validator *get_validator_for_type(std::string_view type_code) const override;
|
||||
|
||||
/// @brief Add category_validator @a v to the list of category validators
|
||||
void add_category_validator(category_validator &&v);
|
||||
|
||||
/// @brief Return the category validator for @a category, may return nullptr
|
||||
const category_validator *get_validator_for_category(std::string_view category) const override;
|
||||
|
||||
/// @brief Add link_validator @a v to the list of link validators
|
||||
void add_link_validator(link_validator &&v);
|
||||
|
||||
/// @brief Return the list of link validators for which the parent is @a category
|
||||
std::vector<const link_validator *> get_links_for_parent(std::string_view category) const override;
|
||||
|
||||
/// @brief Return the list of link validators for which the child is @a category
|
||||
std::vector<const link_validator *> get_links_for_child(std::string_view category) const override;
|
||||
|
||||
void set_name(const std::string &name) { m_name = name; } ///< Set the name of this validator
|
||||
void set_version(const std::string &version) { m_version = version; } ///< Set the version of this validator
|
||||
|
||||
private:
|
||||
// name is fully qualified here:
|
||||
item_validator *get_validator_for_item(std::string_view name) const;
|
||||
|
||||
std::string m_name;
|
||||
std::string m_version;
|
||||
bool m_strict = false;
|
||||
std::set<type_validator> m_type_validators;
|
||||
std::set<category_validator> m_category_validators;
|
||||
std::vector<link_validator> m_link_validators;
|
||||
@@ -476,6 +521,46 @@ class validator
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
class extended_validator : public validator_base
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Construct a new validator object
|
||||
*
|
||||
* @param name The name of the underlying dictionary
|
||||
* @param validators The validators this extended validator is composed off
|
||||
*/
|
||||
extended_validator(std::vector<const validator *> validators);
|
||||
|
||||
extended_validator(const extended_validator &rhs) = delete;
|
||||
extended_validator &operator=(const extended_validator &rhs) = delete;
|
||||
|
||||
/// @brief move constructor
|
||||
extended_validator(extended_validator &&rhs) = default;
|
||||
|
||||
/// @brief move assignment operator
|
||||
extended_validator &operator=(extended_validator &&rhs) = default;
|
||||
|
||||
/// @brief Return the type validator for @a type_code, may return nullptr
|
||||
virtual const type_validator *get_validator_for_type(std::string_view type_code) const override;
|
||||
|
||||
/// @brief Return the category validator for @a category, may return nullptr
|
||||
virtual const category_validator *get_validator_for_category(std::string_view category) const override;
|
||||
|
||||
/// @brief Return the list of link validators for which the parent is @a category
|
||||
virtual std::vector<const link_validator *> get_links_for_parent(std::string_view category) const override;
|
||||
|
||||
/// @brief Return the list of link validators for which the child is @a category
|
||||
virtual std::vector<const link_validator *> get_links_for_child(std::string_view category) const override;
|
||||
|
||||
protected:
|
||||
friend class validator_factory;
|
||||
|
||||
std::vector<const validator *> m_validators;
|
||||
};
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* @brief Validators are globally unique objects, use the validator_factory
|
||||
* class to construct them. This class is a singleton.
|
||||
@@ -488,18 +573,36 @@ class validator_factory
|
||||
static validator_factory &instance();
|
||||
|
||||
/// @brief Return the validator with name @a dictionary_name
|
||||
const validator &operator[](std::string_view dictionary_name);
|
||||
[[deprecated("use construct_validator(const category &audit_conform) instead")]]
|
||||
const validator_base &operator[](std::string_view dictionary_name);
|
||||
|
||||
/// @brief Return a validator for the data contained in an audit_conform category
|
||||
const validator_base &construct_validator(const category &audit_conform);
|
||||
|
||||
/// @brief Construct a new validator with name @a name from resource data with at least version @a version if specified
|
||||
const validator &construct_validator(std::string_view name,
|
||||
std::optional<std::string> version);
|
||||
|
||||
/// @brief Construct a new validator with name @a name from the data in @a is with at least version @a version if specified
|
||||
const validator &construct_validator(std::string_view name,
|
||||
std::optional<std::string> version, std::istream &is);
|
||||
|
||||
/// @brief Construct a new validator with name @a name from the data in @a is
|
||||
const validator &construct_validator(std::string_view name, std::istream &is);
|
||||
const validator &construct_validator(std::string_view name, std::istream &is)
|
||||
{
|
||||
return construct_validator(name, {}, is);
|
||||
}
|
||||
|
||||
private:
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
validator_factory() = default;
|
||||
|
||||
static bool check_version(std::string_view name, std::string_view expected, std::string_view found);
|
||||
|
||||
std::mutex m_mutex;
|
||||
std::list<validator> m_validators;
|
||||
std::list<extended_validator> m_extended_validators;
|
||||
};
|
||||
|
||||
} // namespace cif
|
||||
|
||||
8337
rsrc/mmcif_pdbx.dic
8337
rsrc/mmcif_pdbx.dic
File diff suppressed because it is too large
Load Diff
@@ -164,7 +164,7 @@ class category_index
|
||||
return result;
|
||||
}
|
||||
|
||||
size_t size() const;
|
||||
std::size_t size() const;
|
||||
// bool isValid() const;
|
||||
|
||||
private:
|
||||
@@ -475,12 +475,12 @@ category_index::entry *category_index::erase(category &cat, entry *h, row *k)
|
||||
return fix_up(h);
|
||||
}
|
||||
|
||||
size_t category_index::size() const
|
||||
std::size_t category_index::size() const
|
||||
{
|
||||
std::stack<entry *> s;
|
||||
s.push(m_root);
|
||||
|
||||
size_t result = 0;
|
||||
std::size_t result = 0;
|
||||
|
||||
while (not s.empty())
|
||||
{
|
||||
@@ -544,7 +544,7 @@ category::~category()
|
||||
|
||||
void category::remove_item(std::string_view item_name)
|
||||
{
|
||||
for (size_t ix = 0; ix < m_items.size(); ++ix)
|
||||
for (std::size_t ix = 0; ix < m_items.size(); ++ix)
|
||||
{
|
||||
if (not iequals(item_name, m_items[ix].m_name))
|
||||
continue;
|
||||
@@ -563,7 +563,7 @@ void category::remove_item(std::string_view item_name)
|
||||
|
||||
void category::rename_item(std::string_view from_name, std::string_view to_name)
|
||||
{
|
||||
for (size_t ix = 0; ix < m_items.size(); ++ix)
|
||||
for (std::size_t ix = 0; ix < m_items.size(); ++ix)
|
||||
{
|
||||
if (not iequals(from_name, m_items[ix].m_name))
|
||||
continue;
|
||||
@@ -617,7 +617,7 @@ std::set<uint16_t> category::key_item_indices() const
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
void category::set_validator(const validator *v, datablock &db)
|
||||
void category::set_validator(const validator_base *v, datablock &db)
|
||||
{
|
||||
m_validator = v;
|
||||
|
||||
@@ -696,7 +696,7 @@ bool category::is_valid() const
|
||||
bool result = true;
|
||||
|
||||
if (m_validator == nullptr)
|
||||
throw std::runtime_error("no Validator specified");
|
||||
throw std::runtime_error("no validator specified");
|
||||
|
||||
if (empty())
|
||||
{
|
||||
@@ -718,7 +718,7 @@ bool category::is_valid() const
|
||||
auto iv = m_cat_validator->get_validator_for_item(col.m_name);
|
||||
if (iv == nullptr)
|
||||
{
|
||||
m_validator->report_error(validation_error::unknown_item, col.m_name, m_name, false);
|
||||
m_validator->report_error(validation_error::unknown_item, m_name, col.m_name, false);
|
||||
result = false;
|
||||
}
|
||||
|
||||
@@ -832,7 +832,7 @@ bool category::validate_links() const
|
||||
if (name() == "atom_site" and (parent->name() == "pdbx_poly_seq_scheme" or parent->name() == "entity_poly_seq"))
|
||||
continue;
|
||||
|
||||
size_t missing = 0;
|
||||
std::size_t missing = 0;
|
||||
category first_missing_rows(name());
|
||||
|
||||
for (auto r : *this)
|
||||
@@ -909,7 +909,7 @@ condition category::get_parents_condition(row_handle rh, const category &parentC
|
||||
{
|
||||
condition cond;
|
||||
|
||||
for (size_t ix = 0; ix < link->m_child_keys.size(); ++ix)
|
||||
for (std::size_t ix = 0; ix < link->m_child_keys.size(); ++ix)
|
||||
{
|
||||
auto childValue = rh[link->m_child_keys[ix]];
|
||||
|
||||
@@ -951,7 +951,7 @@ condition category::get_children_condition(row_handle rh, const category &childC
|
||||
{
|
||||
condition cond;
|
||||
|
||||
for (size_t ix = 0; ix < link->m_parent_keys.size(); ++ix)
|
||||
for (std::size_t ix = 0; ix < link->m_parent_keys.size(); ++ix)
|
||||
{
|
||||
auto childKey = link->m_child_keys[ix];
|
||||
auto parentKey = link->m_parent_keys[ix];
|
||||
@@ -1127,14 +1127,14 @@ class save_value
|
||||
const T m_sv;
|
||||
};
|
||||
|
||||
size_t category::erase(condition &&cond)
|
||||
std::size_t category::erase(condition &&cond)
|
||||
{
|
||||
return erase(std::move(cond), {});
|
||||
}
|
||||
|
||||
size_t category::erase(condition &&cond, std::function<void(row_handle)> &&visit)
|
||||
std::size_t category::erase(condition &&cond, std::function<void(row_handle)> &&visit)
|
||||
{
|
||||
size_t result = 0;
|
||||
std::size_t result = 0;
|
||||
|
||||
cond.prepare(*this);
|
||||
|
||||
@@ -1274,7 +1274,7 @@ std::string category::get_unique_value(std::string_view item_name)
|
||||
if (result.empty())
|
||||
{
|
||||
// brain-dead implementation
|
||||
for (size_t ix = 0; ix < size(); ++ix)
|
||||
for (std::size_t ix = 0; ix < size(); ++ix)
|
||||
{
|
||||
// result = m_name + "-" + std::to_string(ix);
|
||||
result = cif_id_for_number(ix);
|
||||
@@ -1321,7 +1321,7 @@ void category::update_value(const std::vector<row_handle> &rows, std::string_vie
|
||||
std::string oldValue{ parent[item_name].text() };
|
||||
std::string value{ value_provider(oldValue) };
|
||||
|
||||
parent.assign(colIx, value, false);
|
||||
update_value(parent.get_row(), colIx, value, false, false);
|
||||
|
||||
for (auto &&[childCat, linked] : m_child_links)
|
||||
{
|
||||
@@ -1331,7 +1331,7 @@ void category::update_value(const std::vector<row_handle> &rows, std::string_vie
|
||||
condition cond;
|
||||
std::string childItemName;
|
||||
|
||||
for (size_t ix = 0; ix < linked->m_parent_keys.size(); ++ix)
|
||||
for (std::size_t ix = 0; ix < linked->m_parent_keys.size(); ++ix)
|
||||
{
|
||||
std::string pk = linked->m_parent_keys[ix];
|
||||
std::string ck = linked->m_child_keys[ix];
|
||||
@@ -1362,7 +1362,7 @@ void category::update_value(const std::vector<row_handle> &rows, std::string_vie
|
||||
{
|
||||
condition cond_c;
|
||||
|
||||
for (size_t ix = 0; ix < linked->m_parent_keys.size(); ++ix)
|
||||
for (std::size_t ix = 0; ix < linked->m_parent_keys.size(); ++ix)
|
||||
{
|
||||
std::string pk = linked->m_parent_keys[ix];
|
||||
std::string ck = linked->m_child_keys[ix];
|
||||
@@ -1380,7 +1380,7 @@ void category::update_value(const std::vector<row_handle> &rows, std::string_vie
|
||||
// oops, we need to split this child, unless a row already exists for the new value
|
||||
condition check;
|
||||
|
||||
for (size_t ix = 0; ix < linked->m_parent_keys.size(); ++ix)
|
||||
for (std::size_t ix = 0; ix < linked->m_parent_keys.size(); ++ix)
|
||||
{
|
||||
std::string pk = linked->m_parent_keys[ix];
|
||||
std::string ck = linked->m_child_keys[ix];
|
||||
@@ -1444,8 +1444,7 @@ void category::update_value(row *row, uint16_t item, std::string_view value, boo
|
||||
// before updating
|
||||
|
||||
bool reinsert = false;
|
||||
if (updateLinked and // an update of an Item's value
|
||||
m_index != nullptr and key_item_indices().count(item))
|
||||
if (m_index != nullptr and key_item_indices().count(item))
|
||||
{
|
||||
reinsert = m_index->find(*this, row);
|
||||
if (reinsert)
|
||||
@@ -1476,7 +1475,7 @@ void category::update_value(row *row, uint16_t item, std::string_view value, boo
|
||||
condition cond;
|
||||
std::string childItemName;
|
||||
|
||||
for (size_t ix = 0; ix < linked->m_parent_keys.size(); ++ix)
|
||||
for (std::size_t ix = 0; ix < linked->m_parent_keys.size(); ++ix)
|
||||
{
|
||||
std::string pk = linked->m_parent_keys[ix];
|
||||
std::string ck = linked->m_child_keys[ix];
|
||||
@@ -1513,7 +1512,7 @@ void category::update_value(row *row, uint16_t item, std::string_view value, boo
|
||||
|
||||
condition cond_n;
|
||||
|
||||
for (size_t ix = 0; ix < linked->m_parent_keys.size(); ++ix)
|
||||
for (std::size_t ix = 0; ix < linked->m_parent_keys.size(); ++ix)
|
||||
{
|
||||
std::string pk = linked->m_parent_keys[ix];
|
||||
std::string ck = linked->m_child_keys[ix];
|
||||
@@ -1698,6 +1697,12 @@ void category::swap_item(uint16_t item_ix, row_handle &a, row_handle &b)
|
||||
auto &ra = *a.m_row;
|
||||
auto &rb = *b.m_row;
|
||||
|
||||
while (ra.size() <= item_ix)
|
||||
ra.emplace_back("");
|
||||
|
||||
while (rb.size() <= item_ix)
|
||||
rb.emplace_back("");
|
||||
|
||||
std::swap(ra.at(item_ix), rb.at(item_ix));
|
||||
}
|
||||
|
||||
@@ -1720,7 +1725,7 @@ void category::sort(std::function<int(row_handle, row_handle)> f)
|
||||
m_tail = rows.back().get_row();
|
||||
|
||||
auto r = m_head;
|
||||
for (size_t i = 1; i < rows.size(); ++i)
|
||||
for (std::size_t i = 1; i < rows.size(); ++i)
|
||||
r = r->m_next = rows[i].get_row();
|
||||
r->m_next = nullptr;
|
||||
|
||||
@@ -1736,7 +1741,7 @@ void category::reorder_by_index()
|
||||
|
||||
namespace detail
|
||||
{
|
||||
size_t write_value(std::ostream &os, std::string_view value, size_t offset, size_t width, bool right_aligned)
|
||||
std::size_t write_value(std::ostream &os, std::string_view value, std::size_t offset, std::size_t width, bool right_aligned)
|
||||
{
|
||||
if (value.find('\n') != std::string::npos or width == 0 or value.length() > 132) // write as text item
|
||||
{
|
||||
@@ -1897,7 +1902,7 @@ void category::write(std::ostream &os, const std::vector<uint16_t> &order, bool
|
||||
{
|
||||
os << "loop_\n";
|
||||
|
||||
std::vector<size_t> itemWidths(m_items.size());
|
||||
std::vector<std::size_t> itemWidths(m_items.size());
|
||||
|
||||
for (auto cix : order)
|
||||
{
|
||||
@@ -1919,7 +1924,7 @@ void category::write(std::ostream &os, const std::vector<uint16_t> &order, bool
|
||||
|
||||
if (v->text().find('\n') == std::string_view::npos)
|
||||
{
|
||||
size_t l = v->text().length();
|
||||
std::size_t l = v->text().length();
|
||||
|
||||
if (not sac_parser::is_unquoted_string(v->text()))
|
||||
l += 2;
|
||||
@@ -1935,11 +1940,11 @@ void category::write(std::ostream &os, const std::vector<uint16_t> &order, bool
|
||||
|
||||
for (auto r = m_head; r != nullptr; r = r->m_next) // loop over rows
|
||||
{
|
||||
size_t offset = 0;
|
||||
std::size_t offset = 0;
|
||||
|
||||
for (uint16_t cix : order)
|
||||
{
|
||||
size_t w = itemWidths[cix];
|
||||
std::size_t w = itemWidths[cix];
|
||||
|
||||
std::string_view s;
|
||||
auto iv = r->get(cix);
|
||||
@@ -1949,7 +1954,7 @@ void category::write(std::ostream &os, const std::vector<uint16_t> &order, bool
|
||||
if (s.empty())
|
||||
s = "?";
|
||||
|
||||
size_t l = s.length();
|
||||
std::size_t l = s.length();
|
||||
if (not sac_parser::is_unquoted_string(s))
|
||||
l += 2;
|
||||
if (l < w)
|
||||
@@ -1977,7 +1982,7 @@ void category::write(std::ostream &os, const std::vector<uint16_t> &order, bool
|
||||
else
|
||||
{
|
||||
// first find the indent level
|
||||
size_t l = 0;
|
||||
std::size_t l = 0;
|
||||
|
||||
for (auto &col : m_items)
|
||||
{
|
||||
@@ -1989,7 +1994,7 @@ void category::write(std::ostream &os, const std::vector<uint16_t> &order, bool
|
||||
|
||||
l += 3;
|
||||
|
||||
size_t width = 1;
|
||||
std::size_t width = 1;
|
||||
|
||||
for (auto cix : order)
|
||||
{
|
||||
@@ -2004,7 +2009,7 @@ void category::write(std::ostream &os, const std::vector<uint16_t> &order, bool
|
||||
if (s.empty())
|
||||
s = "?";
|
||||
|
||||
size_t l2 = s.length();
|
||||
std::size_t l2 = s.length();
|
||||
|
||||
if (not sac_parser::is_unquoted_string(s))
|
||||
l2 += 2;
|
||||
@@ -2030,7 +2035,7 @@ void category::write(std::ostream &os, const std::vector<uint16_t> &order, bool
|
||||
if (s.empty())
|
||||
s = "?";
|
||||
|
||||
size_t offset = l;
|
||||
std::size_t offset = l;
|
||||
if (s.length() + l >= kMaxLineLength)
|
||||
{
|
||||
os << '\n';
|
||||
@@ -2070,7 +2075,7 @@ bool category::operator==(const category &rhs) const
|
||||
typedef std::function<int(std::string_view, std::string_view)> compType;
|
||||
std::vector<std::tuple<std::string, compType>> item_names;
|
||||
std::vector<std::string> keys;
|
||||
std::vector<size_t> keyIx;
|
||||
std::vector<std::size_t> keyIx;
|
||||
|
||||
if (catValidator == nullptr)
|
||||
{
|
||||
|
||||
175
src/compound.cpp
175
src/compound.cpp
@@ -177,89 +177,6 @@ compound::compound(cif::datablock &db)
|
||||
}
|
||||
}
|
||||
|
||||
compound::compound(cif::datablock &db, int)
|
||||
{
|
||||
auto &chemComp = db["chem_comp"];
|
||||
|
||||
if (chemComp.size() != 1)
|
||||
throw std::runtime_error("Invalid compound file, chem_comp should contain a single row");
|
||||
|
||||
cif::tie(m_id, m_name) =
|
||||
chemComp.front().get("id", "name");
|
||||
|
||||
cif::trim(m_name);
|
||||
|
||||
m_type = "NON-POLYMER";
|
||||
|
||||
auto &chemCompAtom = db["chem_comp_atom"];
|
||||
for (auto row : chemCompAtom)
|
||||
{
|
||||
compound_atom atom;
|
||||
std::string type_symbol;
|
||||
cif::tie(atom.id, type_symbol, atom.charge, atom.x, atom.y, atom.z) =
|
||||
row.get("atom_id", "type_symbol", "charge", "x", "y", "z");
|
||||
atom.type_symbol = atom_type_traits(type_symbol).type();
|
||||
|
||||
m_formal_charge += atom.charge;
|
||||
|
||||
m_atoms.push_back(std::move(atom));
|
||||
}
|
||||
|
||||
auto &chemCompBond = db["chem_comp_bond"];
|
||||
for (auto row : chemCompBond)
|
||||
{
|
||||
compound_bond bond;
|
||||
std::string btype;
|
||||
cif::tie(bond.atom_id[0], bond.atom_id[1], btype, bond.aromatic) = row.get("atom_id_1", "atom_id_2", "type", "aromatic");
|
||||
|
||||
using cif::iequals;
|
||||
|
||||
if (iequals(btype, "single"))
|
||||
bond.type = bond_type::sing;
|
||||
else if (iequals(btype, "double"))
|
||||
bond.type = bond_type::doub;
|
||||
else if (iequals(btype, "triple"))
|
||||
bond.type = bond_type::trip;
|
||||
else if (iequals(btype, "deloc") or iequals(btype, "aromat") or iequals(btype, "aromatic"))
|
||||
bond.type = bond_type::delo;
|
||||
else
|
||||
{
|
||||
if (cif::VERBOSE > 0)
|
||||
std::cerr << "Unimplemented chem_comp_bond.type " << btype << " in " << db.name() << '\n';
|
||||
bond.type = bond_type::sing;
|
||||
}
|
||||
m_bonds.push_back(std::move(bond));
|
||||
}
|
||||
|
||||
// reconstruct a formula and weight
|
||||
|
||||
m_formula_weight = 0;
|
||||
|
||||
std::map<atom_type, int> f;
|
||||
for (auto &atom : m_atoms)
|
||||
f[atom.type_symbol] += 1;
|
||||
|
||||
if (f.count(atom_type::C))
|
||||
{
|
||||
atom_type_traits att(atom_type::C);
|
||||
m_formula += att.symbol() + std::to_string(f[atom_type::C]) + ' ';
|
||||
m_formula_weight += att.weight() * f[atom_type::C];
|
||||
}
|
||||
|
||||
for (const auto &[type, count] : f)
|
||||
{
|
||||
if (type == atom_type::C)
|
||||
continue;
|
||||
|
||||
atom_type_traits att(type);
|
||||
m_formula += att.symbol() + std::to_string(count) + ' ';
|
||||
m_formula_weight += att.weight() * count;
|
||||
}
|
||||
|
||||
if (not m_formula.empty())
|
||||
m_formula.pop_back();
|
||||
}
|
||||
|
||||
compound_atom compound::get_atom_by_atom_id(const std::string &atom_id) const
|
||||
{
|
||||
compound_atom result = {};
|
||||
@@ -379,41 +296,17 @@ class compound_factory_impl : public std::enable_shared_from_this<compound_facto
|
||||
|
||||
compound *get(std::string id)
|
||||
{
|
||||
cif::to_upper(id);
|
||||
|
||||
std::shared_lock lock(mMutex);
|
||||
|
||||
compound *result = nullptr;
|
||||
|
||||
// walk the list, see if any of the implementations has the compound already
|
||||
|
||||
for (auto impl = shared_from_this(); impl; impl = impl->m_next)
|
||||
{
|
||||
for (auto cmp : impl->m_compounds)
|
||||
{
|
||||
if (iequals(cmp->id(), id))
|
||||
{
|
||||
result = cmp;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (result)
|
||||
result = impl->create(id);
|
||||
if (result != nullptr)
|
||||
break;
|
||||
}
|
||||
|
||||
if (result == nullptr and m_missing.count(id) == 0)
|
||||
{
|
||||
for (auto impl = shared_from_this(); impl; impl = impl->m_next)
|
||||
{
|
||||
result = impl->create(id);
|
||||
if (result != nullptr)
|
||||
break;
|
||||
}
|
||||
|
||||
if (result == nullptr)
|
||||
m_missing.insert(id);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -444,7 +337,7 @@ class compound_factory_impl : public std::enable_shared_from_this<compound_facto
|
||||
cif::parser::datablock_index m_index;
|
||||
|
||||
std::vector<compound *> m_compounds;
|
||||
std::set<std::string> m_missing;
|
||||
cif::iset m_missing;
|
||||
std::shared_ptr<compound_factory_impl> m_next;
|
||||
};
|
||||
|
||||
@@ -465,6 +358,14 @@ compound_factory_impl::compound_factory_impl(const fs::path &file, std::shared_p
|
||||
|
||||
compound *compound_factory_impl::create(const std::string &id)
|
||||
{
|
||||
// shortcut
|
||||
|
||||
if (m_missing.contains(id))
|
||||
return nullptr;
|
||||
|
||||
if (auto i = find_if(m_compounds.begin(), m_compounds.end(), [id](compound *c) { return c->id() == id; }); i != m_compounds.end())
|
||||
return *i;
|
||||
|
||||
compound *result = nullptr;
|
||||
|
||||
std::unique_ptr<std::istream> ccd;
|
||||
@@ -496,7 +397,7 @@ compound *compound_factory_impl::create(const std::string &id)
|
||||
m_index = parser.index_datablocks();
|
||||
|
||||
if (cif::VERBOSE > 1)
|
||||
std::cout << " done" << std::endl;
|
||||
std::cout << " done\n";
|
||||
|
||||
// reload the resource, perhaps this should be improved...
|
||||
if (m_file.empty())
|
||||
@@ -519,7 +420,7 @@ compound *compound_factory_impl::create(const std::string &id)
|
||||
parser.parse_single_datablock(id, m_index);
|
||||
|
||||
if (cif::VERBOSE > 1)
|
||||
std::cout << " done" << std::endl;
|
||||
std::cout << " done\n";
|
||||
|
||||
if (not file.empty())
|
||||
{
|
||||
@@ -533,6 +434,9 @@ compound *compound_factory_impl::create(const std::string &id)
|
||||
}
|
||||
}
|
||||
|
||||
if (result == nullptr)
|
||||
m_missing.insert(id);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -545,20 +449,6 @@ class local_compound_factory_impl : public compound_factory_impl
|
||||
: compound_factory_impl(next)
|
||||
, m_local_file(file)
|
||||
{
|
||||
const std::regex peptideRx("(?:[lmp]-)?peptide", std::regex::icase);
|
||||
|
||||
for (const auto &[id, name, threeLetterCode, group] :
|
||||
file["comp_list"]["chem_comp"].rows<std::string, std::string, std::string, std::string>("id", "name", "three_letter_code", "group"))
|
||||
{
|
||||
auto &rdb = m_local_file["comp_" + id];
|
||||
if (rdb.empty())
|
||||
{
|
||||
std::cerr << "Missing data in restraint file for id " + id + '\n';
|
||||
continue;
|
||||
}
|
||||
|
||||
construct_compound(rdb, id, name, threeLetterCode, group);
|
||||
}
|
||||
}
|
||||
|
||||
compound *create(const std::string &id) override;
|
||||
@@ -572,11 +462,17 @@ class local_compound_factory_impl : public compound_factory_impl
|
||||
|
||||
compound *local_compound_factory_impl::create(const std::string &id)
|
||||
{
|
||||
if (m_missing.contains(id))
|
||||
return nullptr;
|
||||
|
||||
if (auto i = find_if(m_compounds.begin(), m_compounds.end(), [id](compound *c) { return c->id() == id; }); i != m_compounds.end())
|
||||
return *i;
|
||||
|
||||
compound *result = nullptr;
|
||||
|
||||
for (auto &db : m_local_file)
|
||||
{
|
||||
if (db.name() == "comp_" + id)
|
||||
if (db.name() == id)
|
||||
{
|
||||
auto chem_comp = db.get("chem_comp");
|
||||
if (not chem_comp)
|
||||
@@ -598,6 +494,9 @@ compound *local_compound_factory_impl::create(const std::string &id)
|
||||
}
|
||||
}
|
||||
|
||||
if (result == nullptr)
|
||||
m_missing.insert(id);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -608,11 +507,15 @@ compound *local_compound_factory_impl::construct_compound(const datablock &rdb,
|
||||
|
||||
float formula_weight = 0;
|
||||
int formal_charge = 0;
|
||||
std::map<std::string,size_t> formula_data;
|
||||
std::map<std::string,std::size_t> formula_data;
|
||||
|
||||
for (size_t ord = 1; const auto &[atom_id, type_symbol, type, charge, x, y, z] :
|
||||
rdb["chem_comp_atom"].rows<std::string, std::string, std::string, int, float, float, float>(
|
||||
"atom_id", "type_symbol", "type", "charge", "x", "y", "z"))
|
||||
for (std::size_t ord = 1; const auto &[atom_id, type_symbol, type, charge, x, y, z, xi, yi, zi] :
|
||||
rdb["chem_comp_atom"].rows<std::string, std::string, std::string, int,
|
||||
std::optional<float>, std::optional<float>, std::optional<float>,
|
||||
std::optional<float>, std::optional<float>, std::optional<float>>(
|
||||
"atom_id", "type_symbol", "type", "charge",
|
||||
"model_Cartn_x", "model_Cartn_y", "model_Cartn_z",
|
||||
"pdbx_model_Cartn_x_ideal", "pdbx_model_Cartn_y_ideal", "pdbx_model_Cartn_z_ideal"))
|
||||
{
|
||||
auto atom = cif::atom_type_traits(type_symbol);
|
||||
formula_weight += atom.weight();
|
||||
@@ -624,16 +527,16 @@ compound *local_compound_factory_impl::construct_compound(const datablock &rdb,
|
||||
{ "atom_id", atom_id },
|
||||
{ "type_symbol", type_symbol },
|
||||
{ "charge", charge },
|
||||
{ "model_Cartn_x", x, 3 },
|
||||
{ "model_Cartn_y", y, 3 },
|
||||
{ "model_Cartn_z", z, 3 },
|
||||
{ "model_Cartn_x", x.has_value() ? x : xi, 3 },
|
||||
{ "model_Cartn_y", y.has_value() ? y : yi, 3 },
|
||||
{ "model_Cartn_z", z.has_value() ? z : zi, 3 },
|
||||
{ "pdbx_ordinal", ord++ }
|
||||
});
|
||||
|
||||
formal_charge += charge;
|
||||
}
|
||||
|
||||
for (size_t ord = 1; const auto &[atom_id_1, atom_id_2, type, aromatic] :
|
||||
for (std::size_t ord = 1; const auto &[atom_id_1, atom_id_2, type, aromatic] :
|
||||
rdb["chem_comp_bond"].rows<std::string, std::string, std::string, bool>("atom_id_1", "atom_id_2", "type", "aromatic"))
|
||||
{
|
||||
std::string value_order("SING");
|
||||
|
||||
@@ -76,6 +76,20 @@ namespace detail
|
||||
return this;
|
||||
}
|
||||
|
||||
condition_impl *key_equals_number_condition_impl::prepare(const category &c)
|
||||
{
|
||||
m_item_ix = c.get_item_ix(m_item_name);
|
||||
|
||||
if (c.get_cat_validator() != nullptr and
|
||||
c.key_item_indices().contains(m_item_ix) and
|
||||
c.key_item_indices().size() == 1)
|
||||
{
|
||||
m_single_hit = c[{ { m_item_name, m_value } }];
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
bool found_in_range(condition_impl *c, std::vector<and_condition_impl *>::iterator b, std::vector<and_condition_impl *>::iterator e)
|
||||
{
|
||||
bool result = true;
|
||||
@@ -101,27 +115,33 @@ namespace detail
|
||||
auto first = subs.front();
|
||||
auto &fc = first->m_sub;
|
||||
|
||||
for (auto c : fc)
|
||||
for (size_t fc_i = 0; fc_i < fc.size();)
|
||||
{
|
||||
if (not found_in_range(c, subs.begin() + 1, subs.end()))
|
||||
auto c = fc[fc_i];
|
||||
if (not found_in_range(c, subs.begin() + 1, subs.end())) {
|
||||
++fc_i;
|
||||
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());
|
||||
fc.erase(fc.begin() + fc_i);
|
||||
|
||||
for (auto sub : subs)
|
||||
{
|
||||
auto &ssub = sub->m_sub;
|
||||
|
||||
for (auto sc : ssub)
|
||||
for (size_t ssub_i = 0; ssub_i < ssub.size();)
|
||||
{
|
||||
if (not sc->equals(c))
|
||||
auto sc = ssub[ssub_i];
|
||||
if (not sc->equals(c)) {
|
||||
++ssub_i;
|
||||
continue;
|
||||
}
|
||||
|
||||
ssub.erase(remove(ssub.begin(), ssub.end(), sc), ssub.end());
|
||||
ssub.erase(ssub.begin() + ssub_i);
|
||||
delete sc;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -38,7 +38,18 @@ datablock::datablock(const datablock &db)
|
||||
cat.update_links(*this);
|
||||
}
|
||||
|
||||
void datablock::set_validator(const validator *v)
|
||||
void datablock::load_dictionary()
|
||||
{
|
||||
if (auto *audit_conform = get("audit_conform"); audit_conform and not audit_conform->empty())
|
||||
set_validator(&validator_factory::instance().construct_validator(*audit_conform));
|
||||
}
|
||||
|
||||
void datablock::load_dictionary(std::string_view name)
|
||||
{
|
||||
set_validator(&validator_factory::instance()[name]);
|
||||
}
|
||||
|
||||
void datablock::set_validator(const validator_base *v)
|
||||
{
|
||||
m_validator = v;
|
||||
|
||||
@@ -49,11 +60,12 @@ void datablock::set_validator(const validator *v)
|
||||
}
|
||||
catch (const std::exception &)
|
||||
{
|
||||
m_validator = nullptr;
|
||||
throw_with_nested(std::runtime_error("Error while setting validator in datablock " + m_name));
|
||||
}
|
||||
}
|
||||
|
||||
const validator *datablock::get_validator() const
|
||||
const validator_base *datablock::get_validator() const
|
||||
{
|
||||
return m_validator;
|
||||
}
|
||||
@@ -61,7 +73,7 @@ const validator *datablock::get_validator() const
|
||||
bool datablock::is_valid() const
|
||||
{
|
||||
if (m_validator == nullptr)
|
||||
throw std::runtime_error("Validator not specified");
|
||||
throw std::runtime_error("Validator not specified for datablock data_" + name());
|
||||
|
||||
bool result = true;
|
||||
for (auto &cat : *this)
|
||||
@@ -73,12 +85,12 @@ bool datablock::is_valid() const
|
||||
bool datablock::is_valid()
|
||||
{
|
||||
if (m_validator == nullptr)
|
||||
throw std::runtime_error("Validator not specified");
|
||||
throw std::runtime_error("Validator not specified for datablock data_" + name());
|
||||
|
||||
bool result = true;
|
||||
for (auto &cat : *this)
|
||||
result = cat.is_valid() and result;
|
||||
|
||||
|
||||
// Add or remove the audit_conform block here.
|
||||
if (result)
|
||||
{
|
||||
@@ -99,7 +111,9 @@ bool datablock::is_valid()
|
||||
}
|
||||
}
|
||||
else
|
||||
erase(std::find_if(begin(), end(), [](category &cat) { return cat.name() == "audit_conform"; }), end());
|
||||
erase(std::find_if(begin(), end(), [](category &cat)
|
||||
{ return cat.name() == "audit_conform"; }),
|
||||
end());
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -173,7 +187,7 @@ std::tuple<datablock::iterator, bool> datablock::emplace(std::string_view name)
|
||||
|
||||
if (is_new)
|
||||
{
|
||||
i = insert(end(), {name});
|
||||
i = insert(end(), { name });
|
||||
i->set_validator(m_validator, *this);
|
||||
}
|
||||
|
||||
@@ -234,7 +248,7 @@ namespace
|
||||
return std::get<2>(*i);
|
||||
}
|
||||
|
||||
void calculate_cat_order(cat_order_t &cat_order, iter_t i, const validator &validator)
|
||||
void calculate_cat_order(cat_order_t &cat_order, iter_t i, const validator_base &validator)
|
||||
{
|
||||
if (i == cat_order.end() or get_count(i) >= 0)
|
||||
return;
|
||||
@@ -307,7 +321,7 @@ void datablock::write(std::ostream &os) const
|
||||
else
|
||||
{
|
||||
// mmcif support, sort of. First write the 'entry' Category
|
||||
// and if it exists, _AND_ we have a Validator, write out the
|
||||
// and if it exists, _AND_ we have a validator, write out the
|
||||
// audit_conform record.
|
||||
|
||||
if (auto entry = get("entry"); entry != nullptr)
|
||||
|
||||
@@ -308,17 +308,17 @@ class dictionary_parser : public parser
|
||||
|
||||
using key_type = std::tuple<std::string, std::string, int>;
|
||||
|
||||
std::map<key_type, size_t> linkIndex;
|
||||
std::map<key_type, std::size_t> linkIndex;
|
||||
|
||||
// Each link group consists of a set of keys
|
||||
std::vector<std::tuple<std::vector<std::string>, std::vector<std::string>>> linkKeys;
|
||||
|
||||
auto addLink = [&](size_t ix, const std::string &pk, const std::string &ck)
|
||||
auto addLink = [&](std::size_t ix, const std::string &pk, const std::string &ck)
|
||||
{
|
||||
auto &&[pkeys, ckeys] = linkKeys.at(ix);
|
||||
|
||||
bool found = false;
|
||||
for (size_t i = 0; i < pkeys.size(); ++i)
|
||||
for (std::size_t i = 0; i < pkeys.size(); ++i)
|
||||
{
|
||||
if (pkeys[i] == pk and ckeys[i] == ck)
|
||||
{
|
||||
@@ -357,7 +357,7 @@ class dictionary_parser : public parser
|
||||
linkKeys.push_back({});
|
||||
}
|
||||
|
||||
size_t ix = linkIndex.at(key);
|
||||
std::size_t ix = linkIndex.at(key);
|
||||
addLink(ix, piv->m_item_name, civ->m_item_name);
|
||||
}
|
||||
|
||||
@@ -385,7 +385,7 @@ class dictionary_parser : public parser
|
||||
linkKeys.push_back({});
|
||||
}
|
||||
|
||||
size_t ix = linkIndex.at(key);
|
||||
std::size_t ix = linkIndex.at(key);
|
||||
addLink(ix, piv->m_item_name, civ->m_item_name);
|
||||
}
|
||||
}
|
||||
@@ -488,11 +488,4 @@ validator parse_dictionary(std::string_view name, std::istream &is)
|
||||
return result;
|
||||
}
|
||||
|
||||
void extend_dictionary(validator &v, std::istream &is)
|
||||
{
|
||||
file f;
|
||||
dictionary_parser p(v, is, f);
|
||||
p.load_dictionary();
|
||||
}
|
||||
|
||||
} // namespace cif
|
||||
|
||||
132
src/file.cpp
132
src/file.cpp
@@ -30,19 +30,8 @@
|
||||
namespace cif
|
||||
{
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
void file::set_validator(const validator *v)
|
||||
{
|
||||
m_validator = v;
|
||||
for (auto &db : *this)
|
||||
db.set_validator(v);
|
||||
}
|
||||
|
||||
bool file::is_valid() const
|
||||
{
|
||||
if (m_validator == nullptr)
|
||||
std::runtime_error("No validator loaded explicitly, cannot continue");
|
||||
|
||||
bool result = true;
|
||||
for (auto &d : *this)
|
||||
result = d.is_valid() and result;
|
||||
@@ -55,14 +44,6 @@ bool file::is_valid() const
|
||||
|
||||
bool file::is_valid()
|
||||
{
|
||||
if (m_validator == nullptr)
|
||||
{
|
||||
if (VERBOSE > 0)
|
||||
std::cerr << "No dictionary loaded explicitly, loading default\n";
|
||||
|
||||
load_dictionary();
|
||||
}
|
||||
|
||||
bool result = not empty();
|
||||
|
||||
for (auto &d : *this)
|
||||
@@ -76,56 +57,54 @@ bool file::is_valid()
|
||||
|
||||
bool file::validate_links() const
|
||||
{
|
||||
if (m_validator == nullptr)
|
||||
std::runtime_error("No validator loaded explicitly, cannot continue");
|
||||
|
||||
bool result = true;
|
||||
|
||||
for (auto &db : *this)
|
||||
result = db.validate_links() and result;
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void file::load_dictionary()
|
||||
{
|
||||
if (not empty())
|
||||
{
|
||||
auto *audit_conform = front().get("audit_conform");
|
||||
if (audit_conform and not audit_conform->empty())
|
||||
{
|
||||
std::string name = audit_conform->front().get<std::string>("dict_name");
|
||||
// void file::load_dictionary()
|
||||
// {
|
||||
// if (not empty())
|
||||
// {
|
||||
// auto *audit_conform = front().get("audit_conform");
|
||||
// if (audit_conform and not audit_conform->empty())
|
||||
// {
|
||||
// std::string name = audit_conform->front().get<std::string>("dict_name");
|
||||
|
||||
if (name == "mmcif_pdbx_v50")
|
||||
name = "mmcif_pdbx.dic"; // we had a bug here in libcifpp...
|
||||
// if (name == "mmcif_pdbx_v50")
|
||||
// name = "mmcif_pdbx.dic"; // we had a bug here in libcifpp...
|
||||
|
||||
if (not name.empty())
|
||||
{
|
||||
try
|
||||
{
|
||||
load_dictionary(name);
|
||||
}
|
||||
catch (const std::exception &ex)
|
||||
{
|
||||
if (VERBOSE)
|
||||
std::cerr << "Failed to load dictionary " << std::quoted(name) << ": " << ex.what() << '\n';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// if (not name.empty())
|
||||
// {
|
||||
// try
|
||||
// {
|
||||
// load_dictionary(name);
|
||||
// }
|
||||
// catch (const std::exception &ex)
|
||||
// {
|
||||
// if (VERBOSE)
|
||||
// std::cerr << "Failed to load dictionary " << std::quoted(name) << ": " << ex.what() << '\n';
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// if (not m_validator)
|
||||
// load_dictionary("mmcif_pdbx.dic"); // TODO: maybe incorrect? Perhaps improve?
|
||||
}
|
||||
// // if (not m_validator)
|
||||
// // load_dictionary("mmcif_pdbx.dic"); // TODO: maybe incorrect? Perhaps improve?
|
||||
// }
|
||||
|
||||
void file::load_dictionary(std::string_view name)
|
||||
{
|
||||
set_validator(&validator_factory::instance()[name]);
|
||||
}
|
||||
// void file::load_dictionary(std::string_view name)
|
||||
// {
|
||||
// set_validator(&validator_factory::instance()[name]);
|
||||
// }
|
||||
|
||||
bool file::contains(std::string_view name) const
|
||||
{
|
||||
return std::find_if(begin(), end(), [name](const datablock &db) { return iequals(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)
|
||||
@@ -165,10 +144,7 @@ std::tuple<file::iterator, bool> file::emplace(std::string_view name)
|
||||
}
|
||||
|
||||
if (is_new)
|
||||
{
|
||||
i = insert(end(), { name });
|
||||
i->set_validator(m_validator);
|
||||
}
|
||||
|
||||
assert(i != end());
|
||||
return std::make_tuple(i, is_new);
|
||||
@@ -190,18 +166,44 @@ void file::load(const std::filesystem::path &p)
|
||||
}
|
||||
}
|
||||
|
||||
void file::load(std::istream &is)
|
||||
void file::load(const std::filesystem::path &p, std::string_view dict)
|
||||
{
|
||||
auto saved = m_validator;
|
||||
set_validator(nullptr);
|
||||
load(p, validator_factory::instance().operator[](dict));
|
||||
}
|
||||
|
||||
void file::load(std::istream &is, std::string_view dict)
|
||||
{
|
||||
load(is, validator_factory::instance().operator[](dict));
|
||||
}
|
||||
|
||||
void file::load(const std::filesystem::path &p, const validator_base &v)
|
||||
{
|
||||
gzio::ifstream in(p);
|
||||
if (not in.is_open())
|
||||
throw std::runtime_error("Could not open file '" + p.string() + '\'');
|
||||
|
||||
try
|
||||
{
|
||||
load(in, v);
|
||||
}
|
||||
catch (const std::exception &)
|
||||
{
|
||||
throw_with_nested(std::runtime_error("Error reading file '" + p.string() + '\''));
|
||||
}
|
||||
}
|
||||
|
||||
void file::load(std::istream &is, const validator_base &v)
|
||||
{
|
||||
parser p(is, *this);
|
||||
p.parse_file();
|
||||
for (auto &db : *this)
|
||||
db.set_validator(&v);
|
||||
}
|
||||
|
||||
if (saved != nullptr)
|
||||
set_validator(saved);
|
||||
else
|
||||
load_dictionary();
|
||||
void file::load(std::istream &is)
|
||||
{
|
||||
parser p(is, *this);
|
||||
p.parse_file();
|
||||
}
|
||||
|
||||
void file::save(const std::filesystem::path &p) const
|
||||
|
||||
699
src/model.cpp
699
src/model.cpp
File diff suppressed because it is too large
Load Diff
@@ -837,6 +837,9 @@ void parser::produce_datablock(std::string_view name)
|
||||
|
||||
const auto &[iter, ignore] = m_file.emplace(name);
|
||||
m_datablock = &(*iter);
|
||||
|
||||
if (m_validator)
|
||||
m_datablock->set_validator(m_validator);
|
||||
}
|
||||
|
||||
void parser::produce_category(std::string_view name)
|
||||
|
||||
@@ -182,7 +182,7 @@ std::vector<std::string> MapAsymIDs2ChainIDs(const std::vector<std::string> &asy
|
||||
}
|
||||
|
||||
// support for wrapping text using a 'continuation marker'
|
||||
size_t WriteContinuedLine(std::ostream &pdbFile, std::string header, int &count, int cLen, std::string text, std::string::size_type lStart = 0)
|
||||
std::size_t WriteContinuedLine(std::ostream &pdbFile, std::string header, int &count, int cLen, std::string text, std::string::size_type lStart = 0)
|
||||
{
|
||||
if (lStart == 0)
|
||||
{
|
||||
@@ -217,15 +217,15 @@ size_t WriteContinuedLine(std::ostream &pdbFile, std::string header, int &count,
|
||||
return lines.size();
|
||||
}
|
||||
|
||||
size_t WriteOneContinuedLine(std::ostream &pdbFile, std::string header, int cLen, std::string line, int lStart = 0)
|
||||
std::size_t WriteOneContinuedLine(std::ostream &pdbFile, std::string header, int cLen, std::string line, int lStart = 0)
|
||||
{
|
||||
int count = 0;
|
||||
return WriteContinuedLine(pdbFile, header, count, cLen, line, lStart);
|
||||
}
|
||||
|
||||
size_t WriteCitation(std::ostream &pdbFile, const datablock &db, row_handle r, int reference)
|
||||
std::size_t WriteCitation(std::ostream &pdbFile, const datablock &db, row_handle r, int reference)
|
||||
{
|
||||
size_t result = 0;
|
||||
std::size_t result = 0;
|
||||
|
||||
std::string s1;
|
||||
|
||||
@@ -560,7 +560,7 @@ void WriteTitle(std::ostream &pdbFile, const datablock &db)
|
||||
std::string cs = ++continuation > 1 ? std::to_string(continuation) : std::string();
|
||||
|
||||
pdbFile << cif::format(kRevDatFmt, revNum, cs, date, db.name(), modType);
|
||||
for (size_t i = 0; i < 4; ++i)
|
||||
for (std::size_t i = 0; i < 4; ++i)
|
||||
pdbFile << cif::format(" %-6.6s", (i < types.size() ? types[i] : std::string()));
|
||||
pdbFile << '\n';
|
||||
|
||||
@@ -748,7 +748,7 @@ class Fs : public FBase
|
||||
virtual void out(std::ostream &os)
|
||||
{
|
||||
std::string s{ text() };
|
||||
size_t width = os.width();
|
||||
std::size_t width = os.width();
|
||||
|
||||
if (s.empty())
|
||||
{
|
||||
@@ -2368,7 +2368,7 @@ void WriteRemark280(std::ostream &pdbFile, const datablock &db)
|
||||
|
||||
const char *keys[] = { "pdbx_details", "ph", "method", "temp" };
|
||||
|
||||
for (size_t i = 0; i < (sizeof(keys) / sizeof(const char *)); ++i)
|
||||
for (std::size_t i = 0; i < (sizeof(keys) / sizeof(const char *)); ++i)
|
||||
{
|
||||
const char *c = keys[i];
|
||||
|
||||
@@ -2634,7 +2634,7 @@ void WriteRemark470(std::ostream &pdbFile, const datablock &db)
|
||||
{
|
||||
pdbFile << cif::format("REMARK 470 %3.3s %3.3s %1.1s%4d%1.1s ", modelNr, resName, chainID, seqNr, iCode) << " ";
|
||||
|
||||
for (size_t i = 0; i < 6 and not a.second.empty(); ++i)
|
||||
for (std::size_t i = 0; i < 6 and not a.second.empty(); ++i)
|
||||
{
|
||||
pdbFile << cif2pdbAtomName(a.second.front(), resName, db) << ' ';
|
||||
a.second.pop_front();
|
||||
@@ -3284,7 +3284,7 @@ int WriteMiscellaneousFeatures(std::ostream &pdbFile, const datablock &db)
|
||||
std::string siteID = std::get<0>(s);
|
||||
std::deque<std::string> &res = std::get<1>(s);
|
||||
|
||||
size_t numRes = res.size();
|
||||
std::size_t numRes = res.size();
|
||||
|
||||
int nr = 1;
|
||||
while (res.empty() == false)
|
||||
|
||||
@@ -160,7 +160,7 @@ PDBRecord::~PDBRecord()
|
||||
{
|
||||
}
|
||||
|
||||
void *PDBRecord::operator new(size_t size, size_t vLen)
|
||||
void *PDBRecord::operator new(std::size_t size, std::size_t vLen)
|
||||
{
|
||||
return malloc(size + vLen + 1);
|
||||
}
|
||||
@@ -170,7 +170,7 @@ void PDBRecord::operator delete(void *p)
|
||||
free(p);
|
||||
}
|
||||
|
||||
void PDBRecord::operator delete(void *p, size_t vLen)
|
||||
void PDBRecord::operator delete(void *p, std::size_t vLen)
|
||||
{
|
||||
free(p);
|
||||
}
|
||||
@@ -180,7 +180,7 @@ bool PDBRecord::is(const char *name) const
|
||||
return iequals(mName, name);
|
||||
}
|
||||
|
||||
char PDBRecord::vC(size_t column)
|
||||
char PDBRecord::vC(std::size_t column)
|
||||
{
|
||||
char result = ' ';
|
||||
if (column - 7 < mVlen)
|
||||
@@ -188,7 +188,7 @@ char PDBRecord::vC(size_t column)
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string PDBRecord::vS(size_t columnFirst, size_t columnLast)
|
||||
std::string PDBRecord::vS(std::size_t columnFirst, std::size_t columnLast)
|
||||
{
|
||||
std::string result;
|
||||
|
||||
@@ -272,7 +272,7 @@ int PDBRecord::vI(int columnFirst, int columnLast)
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string PDBRecord::vF(size_t columnFirst, size_t columnLast)
|
||||
std::string PDBRecord::vF(std::size_t columnFirst, std::size_t columnLast)
|
||||
{
|
||||
// for now... TODO: check format?
|
||||
return vS(columnFirst, columnLast);
|
||||
@@ -780,17 +780,17 @@ class PDBFileParser
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
|
||||
char vC(size_t column) const
|
||||
char vC(std::size_t column) const
|
||||
{
|
||||
return mRec->vC(column);
|
||||
}
|
||||
|
||||
std::string vS(size_t columnFirst, size_t columnLast = std::numeric_limits<size_t>::max()) const
|
||||
std::string vS(std::size_t columnFirst, std::size_t columnLast = std::numeric_limits<std::size_t>::max()) const
|
||||
{
|
||||
return mRec->vS(columnFirst, columnLast);
|
||||
}
|
||||
|
||||
std::string vF(size_t columnFirst, size_t columnLast) const
|
||||
std::string vF(std::size_t columnFirst, std::size_t columnLast) const
|
||||
{
|
||||
return mRec->vF(columnFirst, columnLast);
|
||||
}
|
||||
@@ -847,7 +847,7 @@ class PDBFileParser
|
||||
void ParseRemarks();
|
||||
|
||||
// void ParseRemark3();
|
||||
// size_t ParseRemark3(const std::string& program, const Remark3Template templ[], size_t N);
|
||||
// std::size_t ParseRemark3(const std::string& program, const Remark3Template templ[], std::size_t N);
|
||||
// std::string NextRemark3Line();
|
||||
|
||||
void ParseRemark200();
|
||||
@@ -1320,7 +1320,7 @@ void PDBFileParser::PreParseInput(std::istream &is)
|
||||
{
|
||||
std::string siteName = value.substr(5, 3);
|
||||
cif::trim_right(value);
|
||||
size_t n = value.length() - 12;
|
||||
std::size_t n = value.length() - 12;
|
||||
value += std::string(11 - (n % 11), ' ');
|
||||
|
||||
while (lookahead.substr(0, 6) == type and lookahead.substr(11, 3) == siteName)
|
||||
@@ -4202,7 +4202,7 @@ void PDBFileParser::ConstructEntities()
|
||||
|
||||
chains.push_back(std::string{ chain.mDbref.chainID });
|
||||
|
||||
size_t seqLen = 0, seqCanLen = 0;
|
||||
std::size_t seqLen = 0, seqCanLen = 0;
|
||||
|
||||
for (auto &res : chain.mSeqres)
|
||||
{
|
||||
@@ -4265,7 +4265,7 @@ void PDBFileParser::ConstructEntities()
|
||||
}
|
||||
|
||||
auto cat_ps = getCategory("entity_poly_seq");
|
||||
for (size_t i = 0; i < chain.mSeqres.size(); ++i)
|
||||
for (std::size_t i = 0; i < chain.mSeqres.size(); ++i)
|
||||
{
|
||||
auto &rs = chain.mSeqres[i];
|
||||
|
||||
@@ -4335,7 +4335,7 @@ void PDBFileParser::ConstructEntities()
|
||||
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)
|
||||
for (std::size_t i = 0; i < mHets.size(); ++i)
|
||||
{
|
||||
auto &heti = mHets[i];
|
||||
|
||||
@@ -5712,7 +5712,7 @@ void PDBFileParser::ParseCoordinate(int modelNr)
|
||||
stable_sort(atoms.begin(), atoms.end(), rLess);
|
||||
|
||||
// now reiterate the atoms to reorder alternates
|
||||
for (size_t i = 0; i + 1 < atoms.size(); ++i)
|
||||
for (std::size_t i = 0; i + 1 < atoms.size(); ++i)
|
||||
{
|
||||
char altLoc = std::get<3>(atoms[i])->vC(17);
|
||||
|
||||
@@ -5909,7 +5909,8 @@ void PDBFileParser::Parse(std::istream &is, cif::file &result)
|
||||
{
|
||||
try
|
||||
{
|
||||
mDatablock.set_validator(result.get_validator());
|
||||
if (mDatablock.get_validator() == nullptr)
|
||||
mDatablock.load_dictionary();
|
||||
|
||||
PreParseInput(is);
|
||||
|
||||
@@ -6361,7 +6362,7 @@ bool PDBFileParser::PDBChain::SameSequence(const PDBChain &rhs) const
|
||||
{
|
||||
bool result = mSeqres.size() == rhs.mSeqres.size();
|
||||
|
||||
for (size_t i = 0; result and i < mSeqres.size(); ++i)
|
||||
for (std::size_t i = 0; result and i < mSeqres.size(); ++i)
|
||||
result = mSeqres[i].mMonID == rhs.mSeqres[i].mMonID;
|
||||
|
||||
return result;
|
||||
@@ -6373,10 +6374,11 @@ void read_pdb_file(std::istream &pdbFile, cif::file &cifFile)
|
||||
{
|
||||
PDBFileParser p;
|
||||
|
||||
cifFile.load_dictionary("mmcif_pdbx.dic");
|
||||
|
||||
p.Parse(pdbFile, cifFile);
|
||||
|
||||
if (not cifFile.empty() and cifFile.front().get_validator() == nullptr)
|
||||
cifFile.front().load_dictionary("mmcif_pdbx.dic");
|
||||
|
||||
if (not cifFile.is_valid() and cif::VERBOSE >= 0)
|
||||
std::cerr << "Resulting mmCIF file is not valid!\n";
|
||||
}
|
||||
@@ -6421,8 +6423,8 @@ file read(std::istream &is)
|
||||
}
|
||||
|
||||
// Must be a PDB like file, right?
|
||||
if (result.get_validator() == nullptr)
|
||||
result.load_dictionary("mmcif_pdbx.dic");
|
||||
if (not result.empty() and result.front().get_validator() == nullptr)
|
||||
result.front().load_dictionary("mmcif_pdbx.dic");
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -980,8 +980,8 @@ std::string Remark3Parser::nextLine()
|
||||
|
||||
while (mRec != nullptr and mRec->is("REMARK 3"))
|
||||
{
|
||||
size_t valueIndent = 0;
|
||||
for (size_t i = 4; i < mRec->mVlen; ++i)
|
||||
std::size_t valueIndent = 0;
|
||||
for (std::size_t i = 4; i < mRec->mVlen; ++i)
|
||||
{
|
||||
if (mRec->mValue[i] == ' ')
|
||||
continue;
|
||||
@@ -1232,7 +1232,7 @@ void Remark3Parser::storeCapture(const char *category, std::initializer_list<con
|
||||
}
|
||||
// else if (iequals(category, "struct_ncs_dom"))
|
||||
// {
|
||||
// size_t id = cat.size() + 1;
|
||||
// std::size_t id = cat.size() + 1;
|
||||
//
|
||||
// cat.emplace({
|
||||
// { "id", id }
|
||||
@@ -1480,6 +1480,9 @@ bool Remark3Parser::parse(const std::string &expMethod, PDBRecord *r, cif::datab
|
||||
|
||||
for (auto &cat1 : best.parser->mDb)
|
||||
{
|
||||
if (cat1.empty())
|
||||
continue;
|
||||
|
||||
auto &cat2 = db[cat1.name()];
|
||||
|
||||
// copy only the values in the first row for the following categories
|
||||
|
||||
@@ -40,24 +40,24 @@ struct PDBRecord
|
||||
PDBRecord *mNext;
|
||||
uint32_t mLineNr;
|
||||
char mName[11];
|
||||
size_t mVlen;
|
||||
std::size_t mVlen;
|
||||
char mValue[1];
|
||||
|
||||
PDBRecord(uint32_t lineNr, const std::string &name, const std::string &value);
|
||||
~PDBRecord();
|
||||
|
||||
void *operator new(size_t);
|
||||
void *operator new(size_t size, size_t vLen);
|
||||
void *operator new(std::size_t);
|
||||
void *operator new(std::size_t size, std::size_t vLen);
|
||||
|
||||
void operator delete(void *p);
|
||||
void operator delete(void *p, size_t vLen);
|
||||
void operator delete(void *p, std::size_t vLen);
|
||||
|
||||
bool is(const char *name) const;
|
||||
|
||||
char vC(size_t column);
|
||||
std::string vS(size_t columnFirst, size_t columnLast = std::numeric_limits<size_t>::max());
|
||||
char vC(std::size_t column);
|
||||
std::string vS(std::size_t columnFirst, std::size_t columnLast = std::numeric_limits<std::size_t>::max());
|
||||
int vI(int columnFirst, int columnLast);
|
||||
std::string vF(size_t columnFirst, size_t columnLast);
|
||||
std::string vF(std::size_t columnFirst, std::size_t columnLast);
|
||||
};
|
||||
|
||||
} // namespace pdbx
|
||||
@@ -100,10 +100,35 @@ void checkEntities(datablock &db)
|
||||
|
||||
for (auto entity : db["entity"].find("formula_weight"_key == null or "formula_weight"_key == 0))
|
||||
{
|
||||
const auto &[entity_id, type] = entity.get<std::string, std::string>("id", "type");
|
||||
auto &&[entity_id, type] = entity.get<std::string, std::string>("id", "type");
|
||||
|
||||
float formula_weight = 0;
|
||||
|
||||
if (type.empty()) // yes, that happens
|
||||
{
|
||||
const auto comp_id = db["atom_site"].find_first<std::string>("label_entity_id"_key == entity_id, "label_comp_id");
|
||||
auto compound = cf.create(comp_id);
|
||||
if (compound != nullptr)
|
||||
{
|
||||
if (compound->is_base() or compound->is_peptide())
|
||||
type = "polymer";
|
||||
else if (compound->is_water())
|
||||
type = "water";
|
||||
else
|
||||
{
|
||||
if (db["pdbx_entity_branch_link"].contains("entity_id"_key == entity_id))
|
||||
type = "branched";
|
||||
else
|
||||
type = "non-polymer";
|
||||
}
|
||||
}
|
||||
|
||||
if (type.empty())
|
||||
throw std::runtime_error("Entity without type and cannot determine what it should be");
|
||||
|
||||
entity["type"] = type;
|
||||
}
|
||||
|
||||
if (type == "polymer")
|
||||
{
|
||||
int n = 0;
|
||||
@@ -144,9 +169,11 @@ void checkEntities(datablock &db)
|
||||
if (comp_id.has_value())
|
||||
{
|
||||
auto compound = cf.create(*comp_id);
|
||||
assert(compound);
|
||||
if (not compound)
|
||||
throw std::runtime_error("missing information for compound " + *comp_id);
|
||||
{
|
||||
std::cerr << "missing information for compound " << *comp_id << "\n";
|
||||
continue;
|
||||
}
|
||||
formula_weight = compound->formula_weight();
|
||||
}
|
||||
}
|
||||
@@ -211,11 +238,11 @@ void createEntityIDs(datablock &db)
|
||||
lastSeqID = seq_id;
|
||||
}
|
||||
|
||||
std::map<size_t, std::string> entity_ids;
|
||||
std::map<std::size_t, std::string> entity_ids;
|
||||
|
||||
atom_site.add_item("label_entity_id");
|
||||
|
||||
for (size_t i = 0; i < entities.size(); ++i)
|
||||
for (std::size_t i = 0; i < entities.size(); ++i)
|
||||
{
|
||||
if (entity_ids.contains(i))
|
||||
continue;
|
||||
@@ -223,14 +250,14 @@ void createEntityIDs(datablock &db)
|
||||
auto entity_id = std::to_string(i + 1);
|
||||
entity_ids[i] = entity_id;
|
||||
|
||||
for (size_t j = i + 1; j < entities.size(); ++j)
|
||||
for (std::size_t j = i + 1; j < entities.size(); ++j)
|
||||
{
|
||||
if (entities[i] == entities[j])
|
||||
entity_ids[j] = entity_id;
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t ix = 0; auto &e : entities)
|
||||
for (std::size_t ix = 0; auto &e : entities)
|
||||
{
|
||||
auto k = e.front();
|
||||
const auto &entity_id = entity_ids[ix++];
|
||||
@@ -416,6 +443,8 @@ void checkAtomRecords(datablock &db)
|
||||
for (int id : db["entity"].find<int>("type"_key == "polymer", "id"))
|
||||
polymer_entities.insert(id);
|
||||
|
||||
std::set<std::string> missingCompounds;
|
||||
|
||||
for (auto row : atom_site)
|
||||
{
|
||||
residue_key_type k = row.get<std::optional<std::string>,
|
||||
@@ -446,11 +475,18 @@ void checkAtomRecords(datablock &db)
|
||||
std::string asym_id = get_asym_id(k);
|
||||
std::string comp_id = get_comp_id(k);
|
||||
|
||||
if (missingCompounds.contains(comp_id))
|
||||
continue;
|
||||
|
||||
bool is_polymer = polymer_entities.contains(row["label_entity_id"].as<int>());
|
||||
auto compound = cf.create(comp_id);
|
||||
|
||||
if (not compound)
|
||||
throw std::runtime_error("Missing compound information for " + comp_id);
|
||||
{
|
||||
missingCompounds.insert(comp_id);
|
||||
std::cerr << "Missing compound information for " << comp_id << "\n";
|
||||
continue;
|
||||
}
|
||||
|
||||
auto chem_comp_entry = chem_comp.find_first("id"_key == comp_id);
|
||||
|
||||
@@ -590,18 +626,18 @@ void checkAtomAnisotropRecords(datablock &db)
|
||||
row["type_symbol"] = parent["type_symbol"].text();
|
||||
}
|
||||
|
||||
if (row["pdbx_auth_alt_id"].empty())
|
||||
if (row["pdbx_auth_alt_id"].empty() and not parent["pdbx_auth_alt_id"].empty())
|
||||
row["pdbx_auth_alt_id"] = parent["pdbx_auth_alt_id"].text();
|
||||
if (row["pdbx_label_seq_id"].empty())
|
||||
if (row["pdbx_label_seq_id"].empty() and not parent["pdbx_label_seq_id"].empty())
|
||||
row["pdbx_label_seq_id"] = parent["label_seq_id"].text();
|
||||
if (row["pdbx_label_asym_id"].empty())
|
||||
if (row["pdbx_label_asym_id"].empty() and not parent["pdbx_label_asym_id"].empty())
|
||||
row["pdbx_label_asym_id"] = parent["label_asym_id"].text();
|
||||
if (row["pdbx_label_atom_id"].empty())
|
||||
if (row["pdbx_label_atom_id"].empty() and not parent["pdbx_label_atom_id"].empty())
|
||||
row["pdbx_label_atom_id"] = parent["label_atom_id"].text();
|
||||
if (row["pdbx_label_comp_id"].empty())
|
||||
if (row["pdbx_label_comp_id"].empty() and not parent["pdbx_label_comp_id"].empty())
|
||||
row["pdbx_label_comp_id"] = parent["label_comp_id"].text();
|
||||
if (row["pdbx_PDB_model_num"].empty())
|
||||
row["pdbx_PDB_model_num"] = parent["pdbx_PDB_model_num"].text();
|
||||
// if (row["pdbx_PDB_model_num"].empty() and not parent["pdbx_PDB_model_num"].empty())
|
||||
// row["pdbx_PDB_model_num"] = parent["pdbx_PDB_model_num"].text();
|
||||
}
|
||||
|
||||
if (not to_be_deleted.empty())
|
||||
@@ -811,6 +847,18 @@ void createEntityPoly(datablock &db)
|
||||
|
||||
non_std_monomer = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// c_type = "other";
|
||||
|
||||
letter_can = c->one_letter_code();
|
||||
if (letter_can == 0)
|
||||
letter_can = 'X';
|
||||
|
||||
letter = '(' + comp_id + ')';
|
||||
|
||||
non_std_monomer = true;
|
||||
}
|
||||
|
||||
if (type.empty())
|
||||
type = c_type;
|
||||
@@ -877,7 +925,7 @@ void createEntityPoly(datablock &db)
|
||||
|
||||
void createEntityPolySeq(datablock &db)
|
||||
{
|
||||
if (db.get("entity_poly") == nullptr)
|
||||
if (auto cat = db.get("entity_poly"); cat == nullptr or cat->empty())
|
||||
createEntityPoly(db);
|
||||
|
||||
using namespace literals;
|
||||
@@ -928,7 +976,10 @@ void createEntityPolySeq(datablock &db)
|
||||
|
||||
void createPdbxPolySeqScheme(datablock &db)
|
||||
{
|
||||
if (db.get("entity_poly_seq") == nullptr)
|
||||
if (auto cat = db.get("entity_poly"); cat == nullptr or cat->empty())
|
||||
createEntityPoly(db);
|
||||
|
||||
if (auto cat = db.get("entity_poly_seq"); cat == nullptr or cat->empty())
|
||||
createEntityPolySeq(db);
|
||||
|
||||
using namespace literals;
|
||||
@@ -986,6 +1037,10 @@ void comparePolySeqSchemes(datablock &db)
|
||||
auto &ndb_poly_seq_scheme = db["ndb_poly_seq_scheme"];
|
||||
auto &pdbx_poly_seq_scheme = db["pdbx_poly_seq_scheme"];
|
||||
|
||||
// Don't bother if ndb_poly_seq_scheme is empty
|
||||
if (ndb_poly_seq_scheme.empty())
|
||||
return;
|
||||
|
||||
// Since often ndb_poly_seq_scheme only contains an id and mon_id item
|
||||
// we assume that it should match the accompanying pdbx_poly_seq
|
||||
|
||||
@@ -1065,7 +1120,7 @@ bool reconstruct_pdbx(file &file, std::string_view dictionary)
|
||||
// ... and any additional datablock will contain compound information
|
||||
cif::compound_source cs(file);
|
||||
|
||||
if (db.get("atom_site") == nullptr)
|
||||
if (auto cat = db.get("atom_site"); cat == nullptr or cat->empty())
|
||||
throw std::runtime_error("Cannot reconstruct PDBx file, atom data missing");
|
||||
|
||||
auto &validator = validator_factory::instance()[dictionary];
|
||||
@@ -1073,7 +1128,7 @@ bool reconstruct_pdbx(file &file, std::string_view dictionary)
|
||||
std::string entry_id;
|
||||
|
||||
// Phenix files do not have an entry record
|
||||
if (db.get("entry") == nullptr)
|
||||
if (auto cat = db.get("entry"); cat == nullptr or cat->empty())
|
||||
{
|
||||
entry_id = db.name();
|
||||
category entry("entry");
|
||||
@@ -1138,7 +1193,7 @@ bool reconstruct_pdbx(file &file, std::string_view dictionary)
|
||||
iv->m_type != nullptr and
|
||||
iv->m_type->m_primitive_type == cif::DDL_PrimitiveType::Numb;
|
||||
|
||||
for (size_t ix = 0; auto row : cat)
|
||||
for (std::size_t ix = 0; auto row : cat)
|
||||
{
|
||||
if (number)
|
||||
row.assign(key, std::to_string(++ix), false, false);
|
||||
@@ -1320,26 +1375,26 @@ bool reconstruct_pdbx(file &file, std::string_view dictionary)
|
||||
|
||||
db["chem_comp"].reorder_by_index();
|
||||
|
||||
file.load_dictionary(dictionary);
|
||||
db.load_dictionary(dictionary);
|
||||
|
||||
if (db.get("atom_site_anisotrop"))
|
||||
checkAtomAnisotropRecords(db);
|
||||
|
||||
// Now create any missing categories
|
||||
// Next make sure we have struct_asym records
|
||||
if (db.get("struct_asym") == nullptr)
|
||||
if (auto cat = db.get("struct_asym"); cat == nullptr or cat->empty())
|
||||
createStructAsym(db);
|
||||
|
||||
if (db.get("entity") == nullptr)
|
||||
if (auto cat = db.get("entity"); cat == nullptr or cat->empty())
|
||||
createEntity(db);
|
||||
|
||||
// fill in missing formula_weight, e.g.
|
||||
checkEntities(db);
|
||||
|
||||
if (db.get("pdbx_poly_seq_scheme") == nullptr)
|
||||
if (auto cat = db.get("pdbx_poly_seq_scheme"); cat == nullptr or cat->empty())
|
||||
createPdbxPolySeqScheme(db);
|
||||
|
||||
if (db.get("ndb_poly_seq_scheme") != nullptr)
|
||||
if (auto cat = db.get("ndb_poly_seq_scheme"); cat == nullptr or cat->empty())
|
||||
comparePolySeqSchemes(db);
|
||||
|
||||
// skip unknown categories for now
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
namespace cif::pdb
|
||||
{
|
||||
|
||||
condition get_parents_condition(const validator &validator, row_handle rh, const category &parentCat)
|
||||
condition get_parents_condition(const validator_base &validator, row_handle rh, const category &parentCat)
|
||||
{
|
||||
condition result;
|
||||
|
||||
@@ -48,7 +48,7 @@ condition get_parents_condition(const validator &validator, row_handle rh, const
|
||||
{
|
||||
condition cond;
|
||||
|
||||
for (size_t ix = 0; ix < link->m_child_keys.size(); ++ix)
|
||||
for (std::size_t ix = 0; ix < link->m_child_keys.size(); ++ix)
|
||||
{
|
||||
auto childValue = rh[link->m_child_keys[ix]];
|
||||
|
||||
@@ -189,6 +189,7 @@ bool is_valid_pdbx_file(const file &file, std::string_view dictionary, std::erro
|
||||
for (auto asym_id : struct_asym.find<std::string>("entity_id"_key == entity_id, "id"))
|
||||
{
|
||||
if (pdbx_poly_seq_scheme.count(
|
||||
"entity_id"_key == entity_id and
|
||||
"asym_id"_key == asym_id and
|
||||
"mon_id"_key == mon_id and
|
||||
"seq_id"_key == num and
|
||||
@@ -202,6 +203,7 @@ bool is_valid_pdbx_file(const file &file, std::string_view dictionary, std::erro
|
||||
for (const auto &[seq_id, mon_id, hetero] : pdbx_poly_seq_scheme.find<int, std::string, bool>("entity_id"_key == entity_id, "seq_id", "mon_id", "hetero"))
|
||||
{
|
||||
if (entity_poly_seq.count(
|
||||
"entity_id"_key == entity_id and
|
||||
"mon_id"_key == mon_id and
|
||||
"num"_key == seq_id and
|
||||
"hetero"_key == hetero) != 1)
|
||||
@@ -304,8 +306,8 @@ bool is_valid_pdbx_file(const file &file, std::string_view dictionary, std::erro
|
||||
|
||||
if (not seq_can.has_value())
|
||||
{
|
||||
if (cif::VERBOSE > 0)
|
||||
std::clog << "Warning: entity_poly has no sequence for entity_id " << entity_id << '\n';
|
||||
if (cif::VERBOSE > 1)
|
||||
std::clog << "Warning: entity_poly has no canonical sequence for entity_id " << entity_id << '\n';
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
|
||||
#include "symop_table_data.hpp"
|
||||
|
||||
#include <Eigen/Eigenvalues>
|
||||
#include <Eigen/Eigen>
|
||||
|
||||
namespace cif
|
||||
{
|
||||
@@ -103,9 +103,9 @@ sym_op::sym_op(std::string_view s)
|
||||
auto b = s.data();
|
||||
auto e = b + s.length();
|
||||
|
||||
int rnri = 256; // default to unexisting number
|
||||
int rnri = 256; // default to unexisting number
|
||||
auto r = std::from_chars(b, e, rnri);
|
||||
|
||||
|
||||
m_nr = static_cast<uint8_t>(rnri);
|
||||
m_ta = r.ptr[1] - '0';
|
||||
m_tb = r.ptr[2] - '0';
|
||||
@@ -121,14 +121,14 @@ std::string sym_op::string() const
|
||||
auto r = std::to_chars(b, b + sizeof(b), m_nr);
|
||||
if ((bool)r.ec or r.ptr > b + 4)
|
||||
throw std::runtime_error("Could not write out symmetry operation to string");
|
||||
|
||||
|
||||
*r.ptr++ = '_';
|
||||
*r.ptr++ = '0' + m_ta;
|
||||
*r.ptr++ = '0' + m_tb;
|
||||
*r.ptr++ = '0' + m_tc;
|
||||
*r.ptr = 0;
|
||||
|
||||
return { b, static_cast<size_t>(r.ptr - b) };
|
||||
return { b, static_cast<std::size_t>(r.ptr - b) };
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
@@ -163,41 +163,16 @@ transformation::transformation(const matrix3x3<float> &r, const cif::point &t)
|
||||
|
||||
void transformation::try_create_quaternion()
|
||||
{
|
||||
float Qxx = m_rotation(0, 0);
|
||||
float Qxy = m_rotation(0, 1);
|
||||
float Qxz = m_rotation(0, 2);
|
||||
float Qyx = m_rotation(1, 0);
|
||||
float Qyy = m_rotation(1, 1);
|
||||
float Qyz = m_rotation(1, 2);
|
||||
float Qzx = m_rotation(2, 0);
|
||||
float Qzy = m_rotation(2, 1);
|
||||
float Qzz = m_rotation(2, 2);
|
||||
Eigen::Matrix3f rot;
|
||||
|
||||
Eigen::Matrix4f em;
|
||||
rot << m_rotation(0, 0), m_rotation(0, 1), m_rotation(0, 2),
|
||||
m_rotation(1, 0), m_rotation(1, 1), m_rotation(1, 2),
|
||||
m_rotation(2, 0), m_rotation(2, 1), m_rotation(2, 2);
|
||||
|
||||
em << Qxx - Qyy - Qzz, Qyx + Qxy, Qzx + Qxz, Qzy - Qyz,
|
||||
Qyx + Qxy, Qyy - Qxx - Qzz, Qzy + Qyz, Qxz - Qzx,
|
||||
Qzx + Qxz, Qzy + Qyz, Qzz - Qxx - Qyy, Qyx - Qxy,
|
||||
Qzy - Qyz, Qxz - Qzx, Qyx - Qxy, Qxx + Qyy + Qzz;
|
||||
|
||||
Eigen::EigenSolver<Eigen::Matrix4f> es(em / 3);
|
||||
|
||||
auto ev = es.eigenvalues();
|
||||
|
||||
for (size_t j = 0; j < 4; ++j)
|
||||
if (rot * rot.transpose() == Eigen::Matrix3f::Identity() and rot.determinant() == 1)
|
||||
{
|
||||
if (std::abs(ev[j].real() - 1) > 0.01)
|
||||
continue;
|
||||
|
||||
auto col = es.eigenvectors().col(j);
|
||||
|
||||
m_q = normalize(cif::quaternion{
|
||||
static_cast<float>(col(3).real()),
|
||||
static_cast<float>(col(0).real()),
|
||||
static_cast<float>(col(1).real()),
|
||||
static_cast<float>(col(2).real()) });
|
||||
|
||||
break;
|
||||
Eigen::Quaternionf qe(rot);
|
||||
m_q = normalize(cif::quaternion{ qe.w(), qe.x(), qe.y(), qe.z() });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -221,7 +196,7 @@ transformation inverse(const transformation &t)
|
||||
spacegroup::spacegroup(int nr)
|
||||
: m_nr(nr)
|
||||
{
|
||||
const size_t N = kSymopNrTableSize;
|
||||
const std::size_t N = kSymopNrTableSize;
|
||||
int32_t L = 0, R = static_cast<int32_t>(N - 1);
|
||||
while (L <= R)
|
||||
{
|
||||
@@ -234,7 +209,7 @@ spacegroup::spacegroup(int nr)
|
||||
|
||||
m_index = L;
|
||||
|
||||
for (size_t i = L; i < N and kSymopNrTable[i].spacegroup() == m_nr; ++i)
|
||||
for (std::size_t i = L; i < N and kSymopNrTable[i].spacegroup() == m_nr; ++i)
|
||||
emplace_back(kSymopNrTable[i].symop().data());
|
||||
}
|
||||
|
||||
@@ -297,7 +272,7 @@ point spacegroup::operator()(const point &pt, const cell &c, sym_op symop) const
|
||||
{
|
||||
if (symop.m_nr < 1 or symop.m_nr > size())
|
||||
throw std::out_of_range("symmetry operator number out of range");
|
||||
|
||||
|
||||
transformation t = at(symop.m_nr - 1);
|
||||
|
||||
t.m_translation.m_x += symop.m_ta - 5;
|
||||
@@ -316,7 +291,7 @@ point spacegroup::inverse(const point &pt, const cell &c, sym_op symop) const
|
||||
{
|
||||
if (symop.m_nr < 1 or symop.m_nr > size())
|
||||
throw std::out_of_range("symmetry operator number out of range");
|
||||
|
||||
|
||||
transformation t = at(symop.m_nr - 1);
|
||||
|
||||
t.m_translation.m_x += symop.m_ta - 5;
|
||||
@@ -343,7 +318,7 @@ int get_space_group_number(std::string_view spacegroup)
|
||||
|
||||
int result = 0;
|
||||
|
||||
const size_t N = kNrOfSpaceGroups;
|
||||
const std::size_t N = kNrOfSpaceGroups;
|
||||
int32_t L = 0, R = static_cast<int32_t>(N - 1);
|
||||
while (L <= R)
|
||||
{
|
||||
@@ -365,7 +340,7 @@ int get_space_group_number(std::string_view spacegroup)
|
||||
// not found, see if we can find a match based on xHM name
|
||||
if (result == 0)
|
||||
{
|
||||
for (size_t i = 0; i < kNrOfSpaceGroups; ++i)
|
||||
for (std::size_t i = 0; i < kNrOfSpaceGroups; ++i)
|
||||
{
|
||||
auto &sp = kSpaceGroups[i];
|
||||
if (sp.xHM == spacegroup)
|
||||
@@ -395,7 +370,7 @@ int get_space_group_number(std::string_view spacegroup, space_group_name type)
|
||||
|
||||
if (type == space_group_name::full)
|
||||
{
|
||||
const size_t N = kNrOfSpaceGroups;
|
||||
const std::size_t N = kNrOfSpaceGroups;
|
||||
int32_t L = 0, R = static_cast<int32_t>(N - 1);
|
||||
while (L <= R)
|
||||
{
|
||||
@@ -450,13 +425,13 @@ int get_space_group_number(const datablock &db)
|
||||
|
||||
if (_symmetry.size() != 1)
|
||||
throw std::runtime_error("Could not find a unique symmetry in this mmCIF file");
|
||||
|
||||
|
||||
return _symmetry.front().get<int>("Int_Tables_number");
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
std::tuple<float,point,sym_op> crystal::closest_symmetry_copy(point a, point b) const
|
||||
std::tuple<float, point, sym_op> crystal::closest_symmetry_copy(point a, point b) const
|
||||
{
|
||||
if (m_cell.get_a() == 0 or m_cell.get_b() == 0 or m_cell.get_c() == 0)
|
||||
throw std::runtime_error("Invalid cell, contains a dimension that is zero");
|
||||
@@ -475,7 +450,7 @@ std::tuple<float,point,sym_op> crystal::closest_symmetry_copy(point a, point b)
|
||||
|
||||
a = orthogonal(fa, m_cell);
|
||||
|
||||
for (size_t i = 0; i < m_spacegroup.size(); ++i)
|
||||
for (std::size_t i = 0; i < m_spacegroup.size(); ++i)
|
||||
{
|
||||
sym_op s(static_cast<uint8_t>(i + 1));
|
||||
auto &t = m_spacegroup[i];
|
||||
@@ -491,7 +466,7 @@ std::tuple<float,point,sym_op> crystal::closest_symmetry_copy(point a, point b)
|
||||
while (fsb.m_x + 0.5f < fa.m_x)
|
||||
{
|
||||
fsb.m_x += 1;
|
||||
s.m_ta += 1;
|
||||
s.m_ta += 1;
|
||||
}
|
||||
|
||||
while (fsb.m_y - 0.5f > fa.m_y)
|
||||
@@ -503,7 +478,7 @@ std::tuple<float,point,sym_op> crystal::closest_symmetry_copy(point a, point b)
|
||||
while (fsb.m_y + 0.5f < fa.m_y)
|
||||
{
|
||||
fsb.m_y += 1;
|
||||
s.m_tb += 1;
|
||||
s.m_tb += 1;
|
||||
}
|
||||
|
||||
while (fsb.m_z - 0.5f > fa.m_z)
|
||||
@@ -515,7 +490,7 @@ std::tuple<float,point,sym_op> crystal::closest_symmetry_copy(point a, point b)
|
||||
while (fsb.m_z + 0.5f < fa.m_z)
|
||||
{
|
||||
fsb.m_z += 1;
|
||||
s.m_tc += 1;
|
||||
s.m_tc += 1;
|
||||
}
|
||||
|
||||
auto p = orthogonal(fsb, m_cell);
|
||||
|
||||
@@ -426,7 +426,7 @@ const space_group kSpaceGroups[] =
|
||||
out << R"(
|
||||
};
|
||||
|
||||
const size_t kNrOfSpaceGroups = sizeof(kSpaceGroups) / sizeof(space_group);
|
||||
const std::size_t kNrOfSpaceGroups = sizeof(kSpaceGroups) / sizeof(space_group);
|
||||
|
||||
const symop_datablock kSymopNrTable[] = {
|
||||
)";
|
||||
@@ -450,7 +450,7 @@ const symop_datablock kSymopNrTable[] = {
|
||||
|
||||
out << R"(};
|
||||
|
||||
const size_t kSymopNrTableSize = sizeof(kSymopNrTable) / sizeof(symop_datablock);
|
||||
const std::size_t kSymopNrTableSize = sizeof(kSymopNrTable) / sizeof(symop_datablock);
|
||||
|
||||
} // namespace mmcif
|
||||
)";
|
||||
|
||||
@@ -361,7 +361,7 @@ const space_group kSpaceGroups[] =
|
||||
|
||||
};
|
||||
|
||||
const size_t kNrOfSpaceGroups = sizeof(kSpaceGroups) / sizeof(space_group);
|
||||
const std::size_t kNrOfSpaceGroups = sizeof(kSpaceGroups) / sizeof(space_group);
|
||||
|
||||
const symop_datablock kSymopNrTable[] = {
|
||||
// P 1
|
||||
@@ -5286,6 +5286,6 @@ const symop_datablock kSymopNrTable[] = {
|
||||
{ 5005, 4, { -1, 0, 0, 0, 1, 0, 0, 0,-1, 1, 2, 0, 0, 1, 2, } },
|
||||
};
|
||||
|
||||
const size_t kSymopNrTableSize = sizeof(kSymopNrTable) / sizeof(symop_datablock);
|
||||
const std::size_t kSymopNrTableSize = sizeof(kSymopNrTable) / sizeof(symop_datablock);
|
||||
|
||||
} // namespace mmcif
|
||||
|
||||
30
src/text.cpp
30
src/text.cpp
@@ -69,7 +69,7 @@ bool iequals(const char *a, const char *b)
|
||||
{
|
||||
bool result = true;
|
||||
for (; result and *a and *b; ++a, ++b)
|
||||
result = tolower(*a) == tolower(*b);
|
||||
result = kCharToLowerMap[uint8_t(*a)] == kCharToLowerMap[uint8_t(*b)];
|
||||
|
||||
return result and *a == *b;
|
||||
}
|
||||
@@ -80,7 +80,7 @@ int icompare(std::string_view a, std::string_view b)
|
||||
auto ai = a.begin(), bi = b.begin();
|
||||
|
||||
for (; d == 0 and ai != a.end() and bi != b.end(); ++ai, ++bi)
|
||||
d = tolower(*ai) - tolower(*bi);
|
||||
d = (int)kCharToLowerMap[uint8_t(*ai)] - (int)kCharToLowerMap[uint8_t(*bi)];
|
||||
|
||||
if (d == 0)
|
||||
{
|
||||
@@ -98,7 +98,7 @@ int icompare(const char *a, const char *b)
|
||||
int d = 0;
|
||||
|
||||
for (; d == 0 and *a != 0 and *b != 0; ++a, ++b)
|
||||
d = tolower(*a) - tolower(*b);
|
||||
d = (int)kCharToLowerMap[uint8_t(*a)] - (int)kCharToLowerMap[uint8_t(*b)];
|
||||
|
||||
if (d == 0)
|
||||
{
|
||||
@@ -433,10 +433,10 @@ std::string::const_iterator nextLineBreak(std::string::const_iterator text, std:
|
||||
return text;
|
||||
}
|
||||
|
||||
std::vector<std::string> wrapLine(const std::string &text, size_t width)
|
||||
std::vector<std::string> wrapLine(const std::string &text, std::size_t width)
|
||||
{
|
||||
std::vector<std::string> result;
|
||||
std::vector<size_t> offsets = { 0 };
|
||||
std::vector<std::size_t> offsets = { 0 };
|
||||
|
||||
auto b = text.begin();
|
||||
while (b != text.end())
|
||||
@@ -448,18 +448,18 @@ std::vector<std::string> wrapLine(const std::string &text, size_t width)
|
||||
b = e;
|
||||
}
|
||||
|
||||
size_t count = offsets.size() - 1;
|
||||
std::size_t count = offsets.size() - 1;
|
||||
|
||||
std::vector<size_t> minima(count + 1, 1000000);
|
||||
std::vector<std::size_t> minima(count + 1, 1000000);
|
||||
minima[0] = 0;
|
||||
std::vector<size_t> breaks(count + 1, 0);
|
||||
std::vector<std::size_t> breaks(count + 1, 0);
|
||||
|
||||
for (size_t i = 0; i < count; ++i)
|
||||
for (std::size_t i = 0; i < count; ++i)
|
||||
{
|
||||
size_t j = i + 1;
|
||||
std::size_t j = i + 1;
|
||||
while (j <= count)
|
||||
{
|
||||
size_t w = offsets[j] - offsets[i];
|
||||
std::size_t w = offsets[j] - offsets[i];
|
||||
|
||||
if (w > width)
|
||||
break;
|
||||
@@ -467,7 +467,7 @@ std::vector<std::string> wrapLine(const std::string &text, size_t width)
|
||||
while (w > 0 and isspace(text[offsets[i] + w - 1]))
|
||||
--w;
|
||||
|
||||
size_t cost = minima[i];
|
||||
std::size_t cost = minima[i];
|
||||
if (j < count) // last line may be shorter
|
||||
cost += (width - w) * (width - w);
|
||||
|
||||
@@ -481,10 +481,10 @@ std::vector<std::string> wrapLine(const std::string &text, size_t width)
|
||||
}
|
||||
}
|
||||
|
||||
size_t j = count;
|
||||
std::size_t j = count;
|
||||
while (j > 0)
|
||||
{
|
||||
size_t i = breaks[j];
|
||||
std::size_t i = breaks[j];
|
||||
result.push_back(text.substr(offsets[i], offsets[j] - offsets[i]));
|
||||
j = i;
|
||||
}
|
||||
@@ -494,7 +494,7 @@ std::vector<std::string> wrapLine(const std::string &text, size_t width)
|
||||
return result;
|
||||
}
|
||||
|
||||
std::vector<std::string> word_wrap(const std::string &text, size_t width)
|
||||
std::vector<std::string> word_wrap(const std::string &text, std::size_t width)
|
||||
{
|
||||
std::vector<std::string> result;
|
||||
for (auto p : cif::split<std::string>(text, "\n"))
|
||||
|
||||
@@ -63,9 +63,9 @@ std::string get_version_nr()
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
#ifdef _WIN32
|
||||
#if defined(_WIN32) or defined(__MINGW32__)
|
||||
}
|
||||
#include <Windows.h>
|
||||
#include <windows.h>
|
||||
#include <libloaderapi.h>
|
||||
#include <wincon.h>
|
||||
|
||||
@@ -215,7 +215,7 @@ const char* kSpinner[] = {
|
||||
".", "o", "O", "0", "@", "*", " "
|
||||
};
|
||||
|
||||
const size_t kSpinnerCount = sizeof(kSpinner) / sizeof(char*);
|
||||
const std::size_t kSpinnerCount = sizeof(kSpinner) / sizeof(char*);
|
||||
|
||||
const int kSpinnerTimeInterval = 100;
|
||||
|
||||
@@ -235,7 +235,7 @@ void progress_bar_impl::print_progress()
|
||||
float progress = static_cast<float>(m_consumed) / m_max_value;
|
||||
|
||||
if (width < kMinBarWidth)
|
||||
std::cout << (100 * progress) << '%' << std::endl;
|
||||
std::cout << (100 * progress) << "%\n";
|
||||
else
|
||||
{
|
||||
uint32_t bar_width = 7 * width / 10;
|
||||
@@ -329,7 +329,7 @@ void progress_bar_impl::print_done()
|
||||
if (msg.length() < width)
|
||||
msg += std::string(width - msg.length(), ' ');
|
||||
|
||||
std::cout << '\r' << msg << std::endl;
|
||||
std::cout << '\r' << msg << '\n';
|
||||
}
|
||||
|
||||
progress_bar::progress_bar(int64_t inMax, const std::string &inAction)
|
||||
@@ -877,6 +877,21 @@ class resource_pool
|
||||
|
||||
resource_pool::resource_pool()
|
||||
{
|
||||
// directories are searched in reverse order
|
||||
|
||||
// As a last resort, try the location that might have been
|
||||
// used during installation, works only when running on an
|
||||
// OS with a proc file system.
|
||||
|
||||
std::error_code ec;
|
||||
if (auto exefile = fs::read_symlink("/proc/self/exe", ec); not ec and exefile.parent_path().filename() == "bin")
|
||||
{
|
||||
auto install_prefix = exefile.parent_path().parent_path();
|
||||
auto data_dir = install_prefix / "share" / "libcifpp";
|
||||
if (fs::exists(data_dir, ec))
|
||||
pushDir(data_dir);
|
||||
}
|
||||
|
||||
#if defined(DATA_DIR)
|
||||
pushDir(DATA_DIR);
|
||||
#endif
|
||||
|
||||
358
src/validate.cpp
358
src/validate.cpp
@@ -25,6 +25,7 @@
|
||||
*/
|
||||
|
||||
#include "cif++/validate.hpp"
|
||||
#include "cif++/category.hpp"
|
||||
#include "cif++/dictionary_parser.hpp"
|
||||
#include "cif++/gzio.hpp"
|
||||
#include "cif++/utilities.hpp"
|
||||
@@ -138,7 +139,7 @@ int type_validator::compare(std::string_view a, std::string_view b) const
|
||||
ra = selected_charconv<double>::from_chars(a.data(), a.data() + a.length(), da);
|
||||
rb = selected_charconv<double>::from_chars(b.data(), b.data() + b.length(), db);
|
||||
|
||||
if (not (bool)ra.ec and not (bool)rb.ec)
|
||||
if (not(bool) ra.ec and not(bool) rb.ec)
|
||||
{
|
||||
auto d = da - db;
|
||||
if (std::abs(d) > std::numeric_limits<double>::epsilon())
|
||||
@@ -232,7 +233,7 @@ bool item_validator::validate_value(std::string_view value, std::error_code &ec)
|
||||
ec = make_error_code(validation_error::value_is_not_in_enumeration_list);
|
||||
}
|
||||
|
||||
return not (bool)ec;
|
||||
return not(bool) ec;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
@@ -284,6 +285,27 @@ const item_validator *category_validator::get_validator_for_aliased_item(std::st
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
void validator_base::report_error(std::error_code ec, bool fatal) const
|
||||
{
|
||||
if (m_strict or fatal)
|
||||
throw validation_exception(ec);
|
||||
else if (VERBOSE > 0)
|
||||
std::cerr << ec.message() << '\n';
|
||||
}
|
||||
|
||||
void validator_base::report_error(std::error_code ec, std::string_view category,
|
||||
std::string_view item, bool fatal) const
|
||||
{
|
||||
auto ex = item.empty() ? validation_exception(ec, category) : validation_exception(ec, category, item);
|
||||
|
||||
if (m_strict or fatal)
|
||||
throw ex;
|
||||
else if (VERBOSE > 0)
|
||||
std::cerr << ex.what() << '\n';
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
void validator::add_type_validator(type_validator &&v)
|
||||
{
|
||||
auto r = m_type_validators.insert(std::move(v));
|
||||
@@ -353,7 +375,7 @@ void validator::add_link_validator(link_validator &&v)
|
||||
if (ccv == nullptr)
|
||||
throw std::runtime_error("unknown child category " + v.m_child_category);
|
||||
|
||||
for (size_t i = 0; i < v.m_parent_keys.size(); ++i)
|
||||
for (std::size_t i = 0; i < v.m_parent_keys.size(); ++i)
|
||||
{
|
||||
auto piv = pcv->get_validator_for_item(v.m_parent_keys[i]);
|
||||
|
||||
@@ -397,25 +419,76 @@ std::vector<const link_validator *> validator::get_links_for_child(std::string_v
|
||||
return result;
|
||||
}
|
||||
|
||||
void validator::report_error(std::error_code ec, bool fatal) const
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
extended_validator::extended_validator(std::vector<const validator *> validators)
|
||||
: m_validators(validators)
|
||||
{
|
||||
if (m_strict or fatal)
|
||||
throw validation_exception(ec);
|
||||
else
|
||||
std::cerr << ec.message() << '\n';
|
||||
std::vector<std::string> names, versions;
|
||||
|
||||
for (auto v : m_validators)
|
||||
{
|
||||
names.emplace_back(v->name());
|
||||
versions.emplace_back(v->version());
|
||||
m_strict = m_strict or v->is_strict();
|
||||
}
|
||||
|
||||
m_name = cif::join(names, "; ");
|
||||
m_version = cif::join(versions, "; ");
|
||||
}
|
||||
|
||||
void validator::report_error(std::error_code ec, std::string_view category,
|
||||
std::string_view item, bool fatal) const
|
||||
const type_validator *extended_validator::get_validator_for_type(std::string_view type_code) const
|
||||
{
|
||||
auto ex = item.empty() ?
|
||||
validation_exception(ec, category) :
|
||||
validation_exception(ec, category, item);
|
||||
const type_validator *result = nullptr;
|
||||
|
||||
if (m_strict or fatal)
|
||||
throw ex;
|
||||
else
|
||||
std::cerr << ex.what() << '\n';
|
||||
for (auto v : m_validators)
|
||||
{
|
||||
result = v->get_validator_for_type(type_code);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
const category_validator *extended_validator::get_validator_for_category(std::string_view category) const
|
||||
{
|
||||
const category_validator *result = nullptr;
|
||||
|
||||
for (auto v : m_validators)
|
||||
{
|
||||
result = v->get_validator_for_category(category);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
std::vector<const link_validator *> extended_validator::get_links_for_parent(std::string_view category) const
|
||||
{
|
||||
std::vector<const link_validator *> result;
|
||||
|
||||
for (auto v : m_validators)
|
||||
{
|
||||
auto links = v->get_links_for_parent(category);
|
||||
result.insert(result.end(), links.begin(), links.end());
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
std::vector<const link_validator *> extended_validator::get_links_for_child(std::string_view category) const
|
||||
{
|
||||
std::vector<const link_validator *> result;
|
||||
|
||||
for (auto v : m_validators)
|
||||
{
|
||||
auto links = v->get_links_for_child(category);
|
||||
result.insert(result.end(), links.begin(), links.end());
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
@@ -426,101 +499,172 @@ validator_factory &validator_factory::instance()
|
||||
return s_instance;
|
||||
}
|
||||
|
||||
const validator &validator_factory::operator[](std::string_view dictionary_name)
|
||||
const validator_base &validator_factory::operator[](std::string_view dictionary_name)
|
||||
{
|
||||
try
|
||||
{
|
||||
std::lock_guard lock(m_mutex);
|
||||
category audit_conform("audit_conform");
|
||||
for (auto part : cif::split(dictionary_name, ";", true))
|
||||
audit_conform.emplace({ { "dict_name", part } });
|
||||
|
||||
for (auto &validator : m_validators)
|
||||
{
|
||||
if (iequals(validator.name(), dictionary_name))
|
||||
return validator;
|
||||
}
|
||||
|
||||
// not found, try to see if it helps if we tweak the name a little
|
||||
|
||||
// too bad clang version 10 did not have a constructor for std::filesystem::path that accepts a std::string_view
|
||||
std::filesystem::path dictionary(dictionary_name.data(), dictionary_name.data() + dictionary_name.length());
|
||||
|
||||
if (dictionary.extension() != ".dic")
|
||||
{
|
||||
auto dict_name = dictionary.filename().string() + ".dic";
|
||||
|
||||
for (auto &validator : m_validators)
|
||||
{
|
||||
if (iequals(validator.name(), dict_name))
|
||||
return validator;
|
||||
}
|
||||
}
|
||||
|
||||
// not found, add it
|
||||
auto data = load_resource(dictionary_name);
|
||||
|
||||
if (not data and dictionary.extension().string() != ".dic")
|
||||
data = load_resource(dictionary.parent_path() / (dictionary.filename().string() + ".dic"));
|
||||
|
||||
if (data)
|
||||
construct_validator(dictionary_name, *data);
|
||||
else
|
||||
{
|
||||
std::error_code ec;
|
||||
|
||||
// might be a compressed dictionary on disk
|
||||
std::filesystem::path p = dictionary;
|
||||
if (p.extension() == ".dic")
|
||||
p = p.parent_path() / (p.filename().string() + ".gz");
|
||||
else
|
||||
p = p.parent_path() / (p.filename().string() + ".dic.gz");
|
||||
|
||||
#if defined(CACHE_DIR) or defined(DATA_DIR)
|
||||
if (not std::filesystem::exists(p, ec) or ec)
|
||||
{
|
||||
for (const char *dir : {
|
||||
# if defined(CACHE_DIR)
|
||||
CACHE_DIR,
|
||||
# endif
|
||||
# if defined(DATA_DIR)
|
||||
DATA_DIR
|
||||
# endif
|
||||
})
|
||||
{
|
||||
auto p2 = std::filesystem::path(dir) / p;
|
||||
if (std::filesystem::exists(p2, ec) and not ec)
|
||||
{
|
||||
swap(p, p2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (std::filesystem::exists(p, ec) and not ec)
|
||||
{
|
||||
gzio::ifstream in(p);
|
||||
|
||||
if (not in.is_open())
|
||||
throw std::runtime_error("Could not open dictionary (" + p.string() + ")");
|
||||
|
||||
construct_validator(dictionary_name, in);
|
||||
}
|
||||
else
|
||||
throw std::runtime_error("Dictionary not found or defined (" + dictionary.string() + ")");
|
||||
}
|
||||
|
||||
return m_validators.back();
|
||||
}
|
||||
catch (const std::exception &ex)
|
||||
{
|
||||
std::string msg = "Error while loading dictionary ";
|
||||
msg += dictionary_name;
|
||||
std::throw_with_nested(std::runtime_error(msg));
|
||||
}
|
||||
return construct_validator(audit_conform);
|
||||
}
|
||||
|
||||
const validator &validator_factory::construct_validator(std::string_view name, std::istream &is)
|
||||
const validator_base &validator_factory::construct_validator(const category &audit_conform)
|
||||
{
|
||||
return m_validators.emplace_back(parse_dictionary(name, is));
|
||||
if (audit_conform.empty())
|
||||
throw std::runtime_error("Empty audit_conform category, cannot create a validator");
|
||||
|
||||
std::lock_guard lock(m_mutex);
|
||||
|
||||
std::vector<const validator *> validators;
|
||||
|
||||
for (const auto &[name, version] : audit_conform.rows<std::string, std::optional<std::string>>("dict_name", "dict_version"))
|
||||
{
|
||||
auto &v = construct_validator(name, version);
|
||||
validators.emplace_back(&v);
|
||||
}
|
||||
|
||||
if (validators.size() == 1)
|
||||
return *validators.front();
|
||||
|
||||
// override mode, last dictionary is most important
|
||||
std::reverse(validators.begin(), validators.end());
|
||||
|
||||
for (auto &ev : m_extended_validators)
|
||||
{
|
||||
if (ev.m_validators == validators)
|
||||
return ev;
|
||||
}
|
||||
|
||||
return m_extended_validators.emplace_back(validators);
|
||||
}
|
||||
|
||||
const validator &validator_factory::construct_validator(std::string_view name,
|
||||
std::optional<std::string> version)
|
||||
{
|
||||
for (auto &v : m_validators)
|
||||
{
|
||||
if (version.has_value())
|
||||
check_version(name, *version, v.version());
|
||||
|
||||
if (v.name() == name)
|
||||
return v;
|
||||
}
|
||||
|
||||
std::filesystem::path dictionary(name);
|
||||
|
||||
auto data = load_resource(name);
|
||||
|
||||
if (not data and dictionary.extension().string() != ".dic")
|
||||
data = load_resource(dictionary.parent_path() / (dictionary.filename().string() + ".dic"));
|
||||
|
||||
if (not data)
|
||||
{
|
||||
std::error_code ec;
|
||||
|
||||
// might be a compressed dictionary on disk
|
||||
std::filesystem::path p = dictionary;
|
||||
if (p.extension() == ".dic")
|
||||
p = p.parent_path() / (p.filename().string() + ".gz");
|
||||
else
|
||||
p = p.parent_path() / (p.filename().string() + ".dic.gz");
|
||||
|
||||
#if defined(CACHE_DIR) or defined(DATA_DIR)
|
||||
if (not std::filesystem::exists(p, ec) or ec)
|
||||
{
|
||||
for (const char *dir : {
|
||||
# if defined(CACHE_DIR)
|
||||
CACHE_DIR,
|
||||
# endif
|
||||
# if defined(DATA_DIR)
|
||||
DATA_DIR
|
||||
# endif
|
||||
})
|
||||
{
|
||||
auto p2 = std::filesystem::path(dir) / p;
|
||||
if (std::filesystem::exists(p2, ec) and not ec)
|
||||
{
|
||||
swap(p, p2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (std::filesystem::exists(p, ec) and not ec)
|
||||
{
|
||||
auto in = std::make_unique<gzio::ifstream>(p);
|
||||
|
||||
if (not in->is_open())
|
||||
throw std::runtime_error("Could not open dictionary (" + p.string() + ")");
|
||||
|
||||
data.reset(in.release());
|
||||
}
|
||||
else
|
||||
throw std::runtime_error("Dictionary not found or defined (" + dictionary.string() + ")");
|
||||
}
|
||||
|
||||
return construct_validator(name, version, *data);
|
||||
}
|
||||
|
||||
const validator &validator_factory::construct_validator(std::string_view name,
|
||||
std::optional<std::string> version, std::istream &is)
|
||||
{
|
||||
auto v = parse_dictionary(name, is);
|
||||
|
||||
if (version.has_value() and VERBOSE >= 0)
|
||||
{
|
||||
auto vv = v.version();
|
||||
|
||||
if (vv.empty())
|
||||
std::clog << "Could not check version of dictionary " << name << " since this info is missing\n";
|
||||
else
|
||||
check_version(name, *version, vv);
|
||||
}
|
||||
|
||||
return m_validators.emplace_back(std::move(v));
|
||||
}
|
||||
|
||||
bool validator_factory::check_version(std::string_view name, std::string_view expected, std::string_view found)
|
||||
{
|
||||
bool result = true;
|
||||
auto el = cif::split(expected, ".");
|
||||
auto fl = cif::split(found, ".");
|
||||
|
||||
auto eli = el.begin();
|
||||
auto fli = fl.begin();
|
||||
|
||||
while (eli != el.end() and fli != fl.end())
|
||||
{
|
||||
int e_int, f_int;
|
||||
if (auto [ptr, ec] = std::from_chars(eli->begin(), eli->end(), e_int); ec != std::errc{})
|
||||
{
|
||||
std::clog << "Could not parse requested version string for dictionary " << std::quoted(expected) << "\n";
|
||||
result = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (auto [ptr, ec] = std::from_chars(fli->begin(), fli->end(), f_int); ec != std::errc{})
|
||||
{
|
||||
std::clog << "Could not parse version string in dictionary " << name << " " << std::quoted(found) << "\n";
|
||||
result = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (f_int > e_int) // newer version, assume this is ok
|
||||
break;
|
||||
|
||||
if (f_int < e_int)
|
||||
{
|
||||
std::clog << "The version in dictionary " << name << " is lower than requested, this may cause validation errors\n";
|
||||
result = false;
|
||||
break;
|
||||
}
|
||||
|
||||
++eli;
|
||||
++fli;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace cif
|
||||
|
||||
@@ -1,16 +1,20 @@
|
||||
# We're using the older version 2 of Catch2
|
||||
|
||||
find_package(Catch2 QUIET)
|
||||
if(NOT(Catch2_FOUND OR TARGET Catch2))
|
||||
find_package(Catch2 QUIET)
|
||||
|
||||
if(NOT Catch2_FOUND)
|
||||
FetchContent_Declare(
|
||||
Catch2
|
||||
GIT_REPOSITORY https://github.com/catchorg/Catch2.git
|
||||
GIT_TAG v2.13.9)
|
||||
if(NOT Catch2_FOUND)
|
||||
include(FetchContent)
|
||||
|
||||
FetchContent_MakeAvailable(Catch2)
|
||||
FetchContent_Declare(
|
||||
Catch2
|
||||
GIT_REPOSITORY https://github.com/catchorg/Catch2.git
|
||||
GIT_TAG v2.13.9)
|
||||
|
||||
set(Catch2_VERSION "2.13.9")
|
||||
FetchContent_MakeAvailable(Catch2)
|
||||
|
||||
set(Catch2_VERSION "2.13.9")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
list(
|
||||
@@ -30,10 +34,10 @@ add_library(test-main OBJECT "${CMAKE_CURRENT_SOURCE_DIR}/test-main.cpp")
|
||||
|
||||
target_link_libraries(test-main cifpp::cifpp Catch2::Catch2)
|
||||
|
||||
if(${Catch2_VERSION} VERSION_GREATER_EQUAL 3.0.0)
|
||||
target_compile_definitions(test-main PUBLIC CATCH22=0)
|
||||
else()
|
||||
if("${Catch2_VERSION}" VERSION_LESS 3.0.0)
|
||||
target_compile_definitions(test-main PUBLIC CATCH22=1)
|
||||
else()
|
||||
target_compile_definitions(test-main PUBLIC CATCH22=0)
|
||||
endif()
|
||||
|
||||
foreach(CIFPP_TEST IN LISTS CIFPP_tests)
|
||||
@@ -49,8 +53,7 @@ foreach(CIFPP_TEST IN LISTS CIFPP_tests)
|
||||
target_compile_definitions(${CIFPP_TEST} PUBLIC CATCH22=1)
|
||||
endif()
|
||||
|
||||
target_link_libraries(${CIFPP_TEST} PRIVATE Threads::Threads cifpp::cifpp
|
||||
Catch2::Catch2)
|
||||
target_link_libraries(${CIFPP_TEST} PRIVATE cifpp::cifpp Catch2::Catch2)
|
||||
target_include_directories(${CIFPP_TEST} PRIVATE "${EIGEN_INCLUDE_DIR}")
|
||||
|
||||
if(MSVC)
|
||||
|
||||
@@ -32,11 +32,11 @@
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
cif::file operator""_cf(const char *text, size_t length)
|
||||
cif::file operator""_cf(const char *text, std::size_t length)
|
||||
{
|
||||
struct membuf : public std::streambuf
|
||||
{
|
||||
membuf(char *text, size_t length)
|
||||
membuf(char *text, std::size_t length)
|
||||
{
|
||||
this->setg(text, text, text + length);
|
||||
}
|
||||
@@ -53,8 +53,8 @@ TEST_CASE("create_nonpoly_1")
|
||||
cif::VERBOSE = 1;
|
||||
|
||||
cif::file file;
|
||||
file.load_dictionary("mmcif_pdbx.dic");
|
||||
file.emplace("TEST"); // create a datablock
|
||||
auto &&[dbi, ignore] = file.emplace("TEST"); // create a datablock
|
||||
dbi->load_dictionary("mmcif_pdbx.dic");
|
||||
|
||||
cif::mm::structure structure(file);
|
||||
|
||||
@@ -82,7 +82,7 @@ _atom_site.pdbx_formal_charge
|
||||
# that's enough to test with
|
||||
)"_cf;
|
||||
|
||||
atoms.load_dictionary("mmcif_pdbx.dic");
|
||||
atoms.front().load_dictionary("mmcif_pdbx.dic");
|
||||
|
||||
auto &hem_data = atoms["HEM"];
|
||||
auto &atom_site = hem_data["atom_site"];
|
||||
@@ -159,14 +159,14 @@ _struct_asym.details ?
|
||||
_atom_type.symbol C
|
||||
)"_cf;
|
||||
|
||||
expected.load_dictionary("mmcif_pdbx.dic");
|
||||
expected.front().load_dictionary("mmcif_pdbx.dic");
|
||||
|
||||
if (not(expected.front() == structure.get_datablock()))
|
||||
{
|
||||
REQUIRE(false);
|
||||
std::cout << expected.front() << '\n'
|
||||
std::cerr << expected.front() << '\n'
|
||||
<< '\n'
|
||||
<< structure.get_datablock() << '\n';
|
||||
REQUIRE(false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -177,8 +177,8 @@ TEST_CASE("create_nonpoly_2")
|
||||
cif::VERBOSE = 1;
|
||||
|
||||
cif::file file;
|
||||
file.load_dictionary("mmcif_pdbx.dic");
|
||||
file.emplace("TEST"); // create a datablock
|
||||
auto &&[dbi, ignore] = file.emplace("TEST"); // create a datablock
|
||||
dbi->load_dictionary("mmcif_pdbx.dic");
|
||||
|
||||
cif::mm::structure structure(file);
|
||||
|
||||
@@ -270,7 +270,7 @@ _struct_asym.details ?
|
||||
_atom_type.symbol C
|
||||
)"_cf;
|
||||
|
||||
expected.load_dictionary("mmcif_pdbx.dic");
|
||||
expected.front().load_dictionary("mmcif_pdbx.dic");
|
||||
|
||||
REQUIRE(expected.front() == structure.get_datablock());
|
||||
|
||||
@@ -354,7 +354,7 @@ _struct_asym.details ?
|
||||
#
|
||||
)"_cf;
|
||||
|
||||
data.load_dictionary("mmcif_pdbx.dic");
|
||||
data.front().load_dictionary("mmcif_pdbx.dic");
|
||||
|
||||
cif::mm::structure s(data);
|
||||
|
||||
|
||||
@@ -32,11 +32,11 @@
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
cif::file operator""_cf(const char* text, size_t length)
|
||||
cif::file operator""_cf(const char* text, std::size_t length)
|
||||
{
|
||||
struct membuf : public std::streambuf
|
||||
{
|
||||
membuf(char* text, size_t length)
|
||||
membuf(char* text, std::size_t length)
|
||||
{
|
||||
this->setg(text, text, text + length);
|
||||
}
|
||||
@@ -131,7 +131,7 @@ TEST_CASE("sugar_name_1")
|
||||
// auto &db = s.get_datablock();
|
||||
// auto &as = db["atom_site"];
|
||||
|
||||
// for (size_t i = 0; i < 2; ++i)
|
||||
// for (std::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);
|
||||
|
||||
@@ -34,11 +34,11 @@
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
cif::file operator""_cf(const char *text, size_t length)
|
||||
cif::file operator""_cf(const char *text, std::size_t length)
|
||||
{
|
||||
struct membuf : public std::streambuf
|
||||
{
|
||||
membuf(char *text, size_t length)
|
||||
membuf(char *text, std::size_t length)
|
||||
{
|
||||
this->setg(text, text, text + length);
|
||||
}
|
||||
@@ -148,39 +148,37 @@ TEST_CASE("dh_q_0")
|
||||
cif::point axis(1, 0, 0);
|
||||
|
||||
cif::point p(1, 1, 0);
|
||||
|
||||
cif::point t[3] =
|
||||
{
|
||||
|
||||
cif::point t[3] = {
|
||||
{ 0, 1, 0 },
|
||||
{ 0, 0, 0 },
|
||||
{ 1, 0, 0 }
|
||||
};
|
||||
|
||||
auto a = cif::dihedral_angle(t[0], t[1], t[2], p);
|
||||
REQUIRE_THAT(a, Catch::Matchers::WithinRel(0, 0.01f));
|
||||
REQUIRE_THAT(a, Catch::Matchers::WithinRel(0.f, 0.01f));
|
||||
|
||||
auto q = cif::construct_from_angle_axis(90, axis);
|
||||
|
||||
p.rotate(q);
|
||||
|
||||
REQUIRE_THAT(p.m_x, Catch::Matchers::WithinRel(1, 0.01f));
|
||||
REQUIRE_THAT(p.m_y, Catch::Matchers::WithinRel(0, 0.01f));
|
||||
REQUIRE_THAT(p.m_z, Catch::Matchers::WithinRel(1, 0.01f));
|
||||
REQUIRE(std::abs(p.m_x - 1.f) < 0.01f);
|
||||
REQUIRE(std::abs(p.m_y - 0.f) < 0.01f);
|
||||
REQUIRE(std::abs(p.m_z - 1.f) < 0.01f);
|
||||
|
||||
a = cif::dihedral_angle(t[0], t[1], t[2], p);
|
||||
REQUIRE_THAT(a, Catch::Matchers::WithinRel(90, 0.01f));
|
||||
REQUIRE(std::abs(a - 90.f) < 0.01f);
|
||||
|
||||
q = cif::construct_from_angle_axis(-90, axis);
|
||||
|
||||
p.rotate(q);
|
||||
|
||||
REQUIRE_THAT(p.m_x, Catch::Matchers::WithinRel(1, 0.01f));
|
||||
REQUIRE_THAT(p.m_y, Catch::Matchers::WithinRel(1, 0.01f));
|
||||
REQUIRE_THAT(p.m_z, Catch::Matchers::WithinRel(0, 0.01f));
|
||||
REQUIRE(std::abs(p.m_x - 1.f) < 0.01f);
|
||||
REQUIRE(std::abs(p.m_y - 1.f) < 0.01f);
|
||||
REQUIRE(std::abs(p.m_z - 0.f) < 0.01f);
|
||||
|
||||
a = cif::dihedral_angle(t[0], t[1], t[2], p);
|
||||
REQUIRE_THAT(a, Catch::Matchers::WithinRel(0, 0.01f));
|
||||
|
||||
REQUIRE(std::abs(a - 0.f) < 0.01f);
|
||||
}
|
||||
|
||||
TEST_CASE("dh_q_1")
|
||||
@@ -228,62 +226,103 @@ TEST_CASE("dh_q_1")
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
TEST_CASE("m2q_0, *utf::tolerance(0.001f)")
|
||||
// TEST_CASE("m2q_0")
|
||||
// {
|
||||
// for (std::size_t i = 0; i < cif::kSymopNrTableSize; ++i)
|
||||
// {
|
||||
// auto d = cif::kSymopNrTable[i].symop().data();
|
||||
|
||||
// cif::matrix3x3<float> rot;
|
||||
// float Qxx = rot(0, 0) = d[0];
|
||||
// float Qxy = rot(0, 1) = d[1];
|
||||
// float Qxz = rot(0, 2) = d[2];
|
||||
// float Qyx = rot(1, 0) = d[3];
|
||||
// float Qyy = rot(1, 1) = d[4];
|
||||
// float Qyz = rot(1, 2) = d[5];
|
||||
// float Qzx = rot(2, 0) = d[6];
|
||||
// float Qzy = rot(2, 1) = d[7];
|
||||
// float Qzz = rot(2, 2) = d[8];
|
||||
|
||||
// Eigen::Matrix4f em;
|
||||
|
||||
// em << Qxx - Qyy - Qzz, Qyx + Qxy, Qzx + Qxz, Qzy - Qyz,
|
||||
// Qyx + Qxy, Qyy - Qxx - Qzz, Qzy + Qyz, Qxz - Qzx,
|
||||
// Qzx + Qxz, Qzy + Qyz, Qzz - Qxx - Qyy, Qyx - Qxy,
|
||||
// Qzy - Qyz, Qxz - Qzx, Qyx - Qxy, Qxx + Qyy + Qzz;
|
||||
|
||||
// Eigen::EigenSolver<Eigen::Matrix4f> es(em / 3);
|
||||
|
||||
// auto ev = es.eigenvalues();
|
||||
|
||||
// std::size_t bestJ = 0;
|
||||
// float bestEV = -1;
|
||||
|
||||
// for (std::size_t j = 0; j < 4; ++j)
|
||||
// {
|
||||
// if (bestEV < ev[j].real())
|
||||
// {
|
||||
// bestEV = ev[j].real();
|
||||
// bestJ = j;
|
||||
// }
|
||||
// }
|
||||
|
||||
// if (std::abs(bestEV - 1) > 0.01)
|
||||
// continue; // not a rotation matrix
|
||||
|
||||
// auto col = es.eigenvectors().col(bestJ);
|
||||
|
||||
// auto q = normalize(cif::quaternion{
|
||||
// static_cast<float>(col(3).real()),
|
||||
// static_cast<float>(col(0).real()),
|
||||
// static_cast<float>(col(1).real()),
|
||||
// static_cast<float>(col(2).real()) });
|
||||
|
||||
// cif::point p1{ 1, 1, 1 };
|
||||
// cif::point p2 = p1;
|
||||
// p2.rotate(q);
|
||||
|
||||
// cif::point p3 = rot * p1;
|
||||
|
||||
// REQUIRE_THAT(p2.m_x, Catch::Matchers::WithinRel(p3.m_x, 0.01f));
|
||||
// REQUIRE_THAT(p2.m_y, Catch::Matchers::WithinRel(p3.m_y, 0.01f));
|
||||
// REQUIRE_THAT(p2.m_z, Catch::Matchers::WithinRel(p3.m_z, 0.01f));
|
||||
// }
|
||||
// }
|
||||
|
||||
TEST_CASE("m2q_0a")
|
||||
{
|
||||
for (size_t i = 0; i < cif::kSymopNrTableSize; ++i)
|
||||
for (std::size_t i = 0; i < cif::kSymopNrTableSize; ++i)
|
||||
{
|
||||
auto d = cif::kSymopNrTable[i].symop().data();
|
||||
|
||||
cif::matrix3x3<float> rot;
|
||||
float Qxx = rot(0, 0) = d[0];
|
||||
float Qxy = rot(0, 1) = d[1];
|
||||
float Qxz = rot(0, 2) = d[2];
|
||||
float Qyx = rot(1, 0) = d[3];
|
||||
float Qyy = rot(1, 1) = d[4];
|
||||
float Qyz = rot(1, 2) = d[5];
|
||||
float Qzx = rot(2, 0) = d[6];
|
||||
float Qzy = rot(2, 1) = d[7];
|
||||
float Qzz = rot(2, 2) = d[8];
|
||||
Eigen::Matrix3f rot;
|
||||
rot << d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7], d[8];
|
||||
|
||||
Eigen::Matrix4f em;
|
||||
// check to see if this matrix contains a true rotation
|
||||
if (rot * rot.transpose() != Eigen::Matrix3f::Identity() or rot.determinant() != 1)
|
||||
continue;
|
||||
|
||||
em << Qxx - Qyy - Qzz, Qyx + Qxy, Qzx + Qxz, Qzy - Qyz,
|
||||
Qyx + Qxy, Qyy - Qxx - Qzz, Qzy + Qyz, Qxz - Qzx,
|
||||
Qzx + Qxz, Qzy + Qyz, Qzz - Qxx - Qyy, Qyx - Qxy,
|
||||
Qzy - Qyz, Qxz - Qzx, Qyx - Qxy, Qxx + Qyy + Qzz;
|
||||
Eigen::Quaternionf qe(rot);
|
||||
|
||||
Eigen::EigenSolver<Eigen::Matrix4f> es(em / 3);
|
||||
auto q = normalize(cif::quaternion{ qe.w(), qe.x(), qe.y(), qe.z() });
|
||||
|
||||
auto ev = es.eigenvalues();
|
||||
|
||||
size_t bestJ = 0;
|
||||
float bestEV = -1;
|
||||
|
||||
for (size_t j = 0; j < 4; ++j)
|
||||
{
|
||||
if (bestEV < ev[j].real())
|
||||
{
|
||||
bestEV = ev[j].real();
|
||||
bestJ = j;
|
||||
}
|
||||
}
|
||||
|
||||
if (std::abs(bestEV - 1) > 0.01)
|
||||
continue; // not a rotation matrix
|
||||
|
||||
auto col = es.eigenvectors().col(bestJ);
|
||||
|
||||
auto q = normalize(cif::quaternion{
|
||||
static_cast<float>(col(3).real()),
|
||||
static_cast<float>(col(0).real()),
|
||||
static_cast<float>(col(1).real()),
|
||||
static_cast<float>(col(2).real()) });
|
||||
|
||||
cif::point p1{ 1, 1, 1 };
|
||||
cif::point p2 = p1;
|
||||
p2.rotate(q);
|
||||
|
||||
cif::point p3 = rot * p1;
|
||||
cif::matrix3x3<float> rot_c({
|
||||
rot_c(0, 0) = d[0],
|
||||
rot_c(0, 1) = d[1],
|
||||
rot_c(0, 2) = d[2],
|
||||
rot_c(1, 0) = d[3],
|
||||
rot_c(1, 1) = d[4],
|
||||
rot_c(1, 2) = d[5],
|
||||
rot_c(2, 0) = d[6],
|
||||
rot_c(2, 1) = d[7],
|
||||
rot_c(2, 2) = d[8]
|
||||
});
|
||||
|
||||
cif::point p3 = rot_c * p1;
|
||||
|
||||
REQUIRE_THAT(p2.m_x, Catch::Matchers::WithinRel(p3.m_x, 0.01f));
|
||||
REQUIRE_THAT(p2.m_y, Catch::Matchers::WithinRel(p3.m_y, 0.01f));
|
||||
@@ -291,9 +330,9 @@ TEST_CASE("m2q_0, *utf::tolerance(0.001f)")
|
||||
}
|
||||
}
|
||||
|
||||
// "TEST_CASE(m2q_1, *utf::tolerance(0.001f)")
|
||||
// "TEST_CASE(m2q_1")
|
||||
// {
|
||||
// for (size_t i = 0; i < cif::kSymopNrTableSize; ++i)
|
||||
// for (std::size_t i = 0; i < cif::kSymopNrTableSize; ++i)
|
||||
// {
|
||||
// auto d = cif::kSymopNrTable[i].symop().data();
|
||||
|
||||
@@ -317,10 +356,10 @@ TEST_CASE("m2q_0, *utf::tolerance(0.001f)")
|
||||
|
||||
// auto &&[ev, em] = cif::eigen(m * (1/3.0f), false);
|
||||
|
||||
// size_t bestJ = 0;
|
||||
// std::size_t bestJ = 0;
|
||||
// float bestEV = -1;
|
||||
|
||||
// for (size_t j = 0; j < 4; ++j)
|
||||
// for (std::size_t j = 0; j < 4; ++j)
|
||||
// {
|
||||
// if (bestEV < ev[j])
|
||||
// {
|
||||
@@ -337,7 +376,7 @@ TEST_CASE("m2q_0, *utf::tolerance(0.001f)")
|
||||
// static_cast<float>(em(bestJ, 0)),
|
||||
// static_cast<float>(em(bestJ, 1)),
|
||||
// static_cast<float>(em(bestJ, 2)) });
|
||||
|
||||
|
||||
// cif::point p1{ 1, 1, 1 };
|
||||
// cif::point p2 = p1;
|
||||
// p2.rotate(q);
|
||||
@@ -390,17 +429,17 @@ TEST_CASE("symm_3")
|
||||
REQUIRE(sg.get_name() == "P 21 21 2");
|
||||
}
|
||||
|
||||
TEST_CASE("symm_4, *utf::tolerance(0.1f)")
|
||||
TEST_CASE("symm_4")
|
||||
{
|
||||
using namespace cif::literals;
|
||||
|
||||
// based on 2b8h
|
||||
auto sg = cif::spacegroup(154); // p 32 2 1
|
||||
auto c = cif::cell(107.516, 107.516, 338.487, 90.00, 90.00, 120.00);
|
||||
|
||||
cif::point a{ -8.688, 79.351, 10.439 }; // O6 NAG A 500
|
||||
cif::point b{ -35.356, 33.693, -3.236 }; // CG2 THR D 400
|
||||
cif::point sb( -6.916, 79.34, 3.236); // 4_565 copy of b
|
||||
|
||||
cif::point a{ -8.688, 79.351, 10.439 }; // O6 NAG A 500
|
||||
cif::point b{ -35.356, 33.693, -3.236 }; // CG2 THR D 400
|
||||
cif::point sb(-6.916, 79.34, 3.236); // 4_565 copy of b
|
||||
|
||||
REQUIRE_THAT(distance(a, sg(a, c, "1_455"_symop)), Catch::Matchers::WithinRel(static_cast<float>(c.get_a()), 0.01f));
|
||||
REQUIRE_THAT(distance(a, sg(a, c, "1_545"_symop)), Catch::Matchers::WithinRel(static_cast<float>(c.get_b()), 0.01f));
|
||||
@@ -411,12 +450,12 @@ TEST_CASE("symm_4, *utf::tolerance(0.1f)")
|
||||
REQUIRE_THAT(sb.m_y, Catch::Matchers::WithinRel(sb2.m_y, 0.01f));
|
||||
REQUIRE_THAT(sb.m_z, Catch::Matchers::WithinRel(sb2.m_z, 0.01f));
|
||||
|
||||
REQUIRE_THAT(distance(a, sb2), Catch::Matchers::WithinRel(7.42f, 0.01f));
|
||||
REQUIRE_THAT(distance(a, sb2), Catch::Matchers::WithinRel(7.42f, 0.01f));
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
TEST_CASE("symm_4wvp_1, *utf::tolerance(0.1f)")
|
||||
TEST_CASE("symm_4wvp_1")
|
||||
{
|
||||
using namespace cif::literals;
|
||||
|
||||
@@ -427,7 +466,7 @@ TEST_CASE("symm_4wvp_1, *utf::tolerance(0.1f)")
|
||||
|
||||
cif::crystal c(db);
|
||||
|
||||
cif::point p{ -78.722, 98.528, 11.994 };
|
||||
cif::point p{ -78.722, 98.528, 11.994 };
|
||||
auto a = s.get_residue("A", 10, "").get_atom_by_atom_id("O");
|
||||
|
||||
auto sp1 = c.symmetry_copy(a.get_location(), "2_565"_symop);
|
||||
@@ -442,10 +481,9 @@ TEST_CASE("symm_4wvp_1, *utf::tolerance(0.1f)")
|
||||
REQUIRE_THAT(sp2.m_x, Catch::Matchers::WithinAbs(p.m_x, 0.5f));
|
||||
REQUIRE_THAT(sp2.m_y, Catch::Matchers::WithinAbs(p.m_y, 0.5f));
|
||||
REQUIRE_THAT(sp2.m_z, Catch::Matchers::WithinAbs(p.m_z, 0.5f));
|
||||
|
||||
}
|
||||
|
||||
TEST_CASE("symm_2bi3_1, *utf::tolerance(0.1f)")
|
||||
TEST_CASE("symm_2bi3_1")
|
||||
{
|
||||
cif::file f(gTestDir / "2bi3.cif.gz");
|
||||
|
||||
@@ -455,18 +493,15 @@ TEST_CASE("symm_2bi3_1, *utf::tolerance(0.1f)")
|
||||
cif::crystal c(db);
|
||||
|
||||
auto struct_conn = db["struct_conn"];
|
||||
for (const auto &[
|
||||
asym1, seqid1, authseqid1, atomid1, symm1,
|
||||
asym2, seqid2, authseqid2, atomid2, symm2,
|
||||
dist] : struct_conn.find<
|
||||
std::string,int,std::string,std::string,std::string,
|
||||
std::string,int,std::string,std::string,std::string,
|
||||
float>(
|
||||
cif::key("ptnr1_symmetry") != "1_555" or cif::key("ptnr2_symmetry") != "1_555",
|
||||
"ptnr1_label_asym_id", "ptnr1_label_seq_id", "ptnr1_auth_seq_id", "ptnr1_label_atom_id", "ptnr1_symmetry",
|
||||
"ptnr2_label_asym_id", "ptnr2_label_seq_id", "ptnr2_auth_seq_id", "ptnr2_label_atom_id", "ptnr2_symmetry",
|
||||
"pdbx_dist_value"
|
||||
))
|
||||
for (const auto &[asym1, seqid1, authseqid1, atomid1, symm1,
|
||||
asym2, seqid2, authseqid2, atomid2, symm2,
|
||||
dist] : struct_conn.find<std::string, int, std::string, std::string, std::string,
|
||||
std::string, int, std::string, std::string, std::string,
|
||||
float>(
|
||||
cif::key("ptnr1_symmetry") != "1_555" or cif::key("ptnr2_symmetry") != "1_555",
|
||||
"ptnr1_label_asym_id", "ptnr1_label_seq_id", "ptnr1_auth_seq_id", "ptnr1_label_atom_id", "ptnr1_symmetry",
|
||||
"ptnr2_label_asym_id", "ptnr2_label_seq_id", "ptnr2_auth_seq_id", "ptnr2_label_atom_id", "ptnr2_symmetry",
|
||||
"pdbx_dist_value"))
|
||||
{
|
||||
auto &r1 = s.get_residue(asym1, seqid1, authseqid1);
|
||||
auto &r2 = s.get_residue(asym2, seqid2, authseqid2);
|
||||
@@ -492,7 +527,7 @@ TEST_CASE("symm_2bi3_1, *utf::tolerance(0.1f)")
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("symm_2bi3_1a, *utf::tolerance(0.1f)")
|
||||
TEST_CASE("symm_2bi3_1a")
|
||||
{
|
||||
using namespace cif::literals;
|
||||
|
||||
@@ -504,23 +539,20 @@ TEST_CASE("symm_2bi3_1a, *utf::tolerance(0.1f)")
|
||||
auto struct_conn = db["struct_conn"];
|
||||
auto atom_site = db["atom_site"];
|
||||
|
||||
for (const auto &[
|
||||
asym1, seqid1, authseqid1, atomid1, symm1,
|
||||
asym2, seqid2, authseqid2, atomid2, symm2,
|
||||
dist] : struct_conn.find<
|
||||
std::string,std::optional<int>,std::string,std::string,std::string,
|
||||
std::string,std::optional<int>,std::string,std::string,std::string,
|
||||
float>(
|
||||
cif::key("ptnr1_symmetry") != "1_555" or cif::key("ptnr2_symmetry") != "1_555",
|
||||
"ptnr1_label_asym_id", "ptnr1_label_seq_id", "ptnr1_auth_seq_id", "ptnr1_label_atom_id", "ptnr1_symmetry",
|
||||
"ptnr2_label_asym_id", "ptnr2_label_seq_id", "ptnr2_auth_seq_id", "ptnr2_label_atom_id", "ptnr2_symmetry",
|
||||
"pdbx_dist_value"
|
||||
))
|
||||
for (const auto &[asym1, seqid1, authseqid1, atomid1, symm1,
|
||||
asym2, seqid2, authseqid2, atomid2, symm2,
|
||||
dist] : struct_conn.find<std::string, std::optional<int>, std::string, std::string, std::string,
|
||||
std::string, std::optional<int>, std::string, std::string, std::string,
|
||||
float>(
|
||||
cif::key("ptnr1_symmetry") != "1_555" or cif::key("ptnr2_symmetry") != "1_555",
|
||||
"ptnr1_label_asym_id", "ptnr1_label_seq_id", "ptnr1_auth_seq_id", "ptnr1_label_atom_id", "ptnr1_symmetry",
|
||||
"ptnr2_label_asym_id", "ptnr2_label_seq_id", "ptnr2_auth_seq_id", "ptnr2_label_atom_id", "ptnr2_symmetry",
|
||||
"pdbx_dist_value"))
|
||||
{
|
||||
cif::point p1 = atom_site.find1<float,float,float>(
|
||||
cif::point p1 = atom_site.find1<float, float, float>(
|
||||
"label_asym_id"_key == asym1 and "label_seq_id"_key == seqid1 and "auth_seq_id"_key == authseqid1 and "label_atom_id"_key == atomid1,
|
||||
"cartn_x", "cartn_y", "cartn_z");
|
||||
cif::point p2 = atom_site.find1<float,float,float>(
|
||||
cif::point p2 = atom_site.find1<float, float, float>(
|
||||
"label_asym_id"_key == asym2 and "label_seq_id"_key == seqid2 and "auth_seq_id"_key == authseqid2 and "label_atom_id"_key == atomid2,
|
||||
"cartn_x", "cartn_y", "cartn_z");
|
||||
|
||||
@@ -540,7 +572,7 @@ TEST_CASE("symm_2bi3_1a, *utf::tolerance(0.1f)")
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("symm_3bwh_1, *utf::tolerance(0.1f)")
|
||||
TEST_CASE("symm_3bwh_1")
|
||||
{
|
||||
cif::file f(gTestDir / "3bwh.cif.gz");
|
||||
|
||||
@@ -555,15 +587,15 @@ TEST_CASE("symm_3bwh_1, *utf::tolerance(0.1f)")
|
||||
{
|
||||
if (a1 == a2)
|
||||
continue;
|
||||
|
||||
const auto&[ d, p, so ] = c.closest_symmetry_copy(a1.get_location(), a2.get_location());
|
||||
|
||||
const auto &[d, p, so] = c.closest_symmetry_copy(a1.get_location(), a2.get_location());
|
||||
|
||||
REQUIRE_THAT(d, Catch::Matchers::WithinAbs(distance(a1.get_location(), p), 0.5f));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("volume_3bwh_1, *utf::tolerance(0.1f)")
|
||||
TEST_CASE("volume_3bwh_1")
|
||||
{
|
||||
cif::file f(gTestDir / "1juh.cif.gz");
|
||||
|
||||
@@ -573,4 +605,3 @@ TEST_CASE("volume_3bwh_1, *utf::tolerance(0.1f)")
|
||||
|
||||
REQUIRE_THAT(c.get_cell().get_volume(), Catch::Matchers::WithinRel(741009.625f, 0.01f));
|
||||
}
|
||||
|
||||
|
||||
@@ -34,11 +34,11 @@
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
cif::file operator""_cf(const char *text, size_t length)
|
||||
cif::file operator""_cf(const char *text, std::size_t length)
|
||||
{
|
||||
struct membuf : public std::streambuf
|
||||
{
|
||||
membuf(char *text, size_t length)
|
||||
membuf(char *text, std::size_t length)
|
||||
{
|
||||
this->setg(text, text, text + length);
|
||||
}
|
||||
@@ -50,6 +50,47 @@ cif::file operator""_cf(const char *text, size_t length)
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
TEST_CASE("text_1")
|
||||
{
|
||||
CHECK(cif::iequals("TEST", "test"));
|
||||
CHECK(cif::iequals(std::string_view{"TEST"}, std::string_view{"test"}));
|
||||
|
||||
CHECK(cif::icompare("TEST", "test") == 0);
|
||||
CHECK(cif::icompare(std::string_view{"TEST"}, std::string_view{"test"}) == 0);
|
||||
|
||||
CHECK(cif::icompare("TEST1", "test") > 0);
|
||||
CHECK(cif::icompare(std::string_view{"TEST1"}, std::string_view{"test"}) > 0);
|
||||
|
||||
CHECK(cif::icompare("aap", "noot") < 0);
|
||||
CHECK(cif::icompare(std::string_view{"aap"}, std::string_view{"noot"}) < 0);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
TEST_CASE("from_chars_1")
|
||||
{
|
||||
auto f = R"(data_TEST
|
||||
#
|
||||
loop_
|
||||
_test.v
|
||||
616.487
|
||||
616.487000
|
||||
)"_cf;
|
||||
|
||||
auto &db = f.front();
|
||||
auto &c = db.front();
|
||||
|
||||
auto r1 = c.front();
|
||||
REQUIRE(r1.get<double>("v") == 616.487);
|
||||
REQUIRE(r1["v"].compare(616.487) == 0);
|
||||
|
||||
auto r2 = c.back();
|
||||
REQUIRE(r2.get<double>("v") == 616.487);
|
||||
REQUIRE(r2["v"].compare(616.487) == 0);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
TEST_CASE("id_1")
|
||||
{
|
||||
REQUIRE(cif::cif_id_for_number(0) == "A");
|
||||
@@ -240,7 +281,7 @@ TEST_CASE("r_2")
|
||||
{
|
||||
cif::category c("foo");
|
||||
|
||||
for (size_t i = 1; i < 256; ++i)
|
||||
for (std::size_t i = 1; i < 256; ++i)
|
||||
{
|
||||
c.emplace({ { "id", i },
|
||||
{ "txt", std::string(i, 'x') } });
|
||||
@@ -537,7 +578,7 @@ _test.value
|
||||
REQUIRE(not t.empty());
|
||||
REQUIRE(t.front()["name"].as<std::string>() == "aap");
|
||||
|
||||
auto t2 = test.find(cif::key("value") == 1.2f);
|
||||
auto t2 = test.find(cif::key("value") == 1.2);
|
||||
REQUIRE(not t2.empty());
|
||||
REQUIRE(t2.front()["name"].as<std::string>() == "mies");
|
||||
}
|
||||
@@ -572,6 +613,28 @@ _test.value
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
TEST_CASE("compare-with-float")
|
||||
{
|
||||
auto f = R"(data_TEST
|
||||
#
|
||||
loop_
|
||||
_test.id
|
||||
_test.value
|
||||
1 1.0
|
||||
2 2.0
|
||||
3 3.0
|
||||
4 ?
|
||||
5 .
|
||||
)"_cf;
|
||||
|
||||
auto &db = f.front();
|
||||
auto &cat = db["test"];
|
||||
|
||||
CHECK(cat.find_first<int>(cif::key("value") == 1.0, "id") == 1);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
TEST_CASE("sw_1")
|
||||
{
|
||||
using namespace cif::literals;
|
||||
@@ -700,7 +763,7 @@ save__cat_2.desc
|
||||
|
||||
struct membuf : public std::streambuf
|
||||
{
|
||||
membuf(char *text, size_t length)
|
||||
membuf(char *text, std::size_t length)
|
||||
{
|
||||
this->setg(text, text, text + length);
|
||||
}
|
||||
@@ -711,7 +774,6 @@ save__cat_2.desc
|
||||
auto validator = cif::parse_dictionary("test", is_dict);
|
||||
|
||||
cif::file f;
|
||||
f.set_validator(&validator);
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
@@ -735,14 +797,14 @@ _cat_2.desc
|
||||
|
||||
struct data_membuf : public std::streambuf
|
||||
{
|
||||
data_membuf(char *text, size_t length)
|
||||
data_membuf(char *text, std::size_t length)
|
||||
{
|
||||
this->setg(text, text, text + length);
|
||||
}
|
||||
} data_buffer(const_cast<char *>(data), sizeof(data) - 1);
|
||||
|
||||
std::istream is_data(&data_buffer);
|
||||
f.load(is_data);
|
||||
f.load(is_data, validator);
|
||||
|
||||
SECTION("one")
|
||||
{
|
||||
@@ -853,7 +915,7 @@ save__cat_1.c
|
||||
|
||||
struct membuf : public std::streambuf
|
||||
{
|
||||
membuf(char *text, size_t length)
|
||||
membuf(char *text, std::size_t length)
|
||||
{
|
||||
this->setg(text, text, text + length);
|
||||
}
|
||||
@@ -864,7 +926,6 @@ save__cat_1.c
|
||||
auto validator = cif::parse_dictionary("test", is_dict);
|
||||
|
||||
cif::file f;
|
||||
f.set_validator(&validator);
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
@@ -880,14 +941,14 @@ mies Mies
|
||||
|
||||
struct data_membuf : public std::streambuf
|
||||
{
|
||||
data_membuf(char *text, size_t length)
|
||||
data_membuf(char *text, std::size_t length)
|
||||
{
|
||||
this->setg(text, text, text + length);
|
||||
}
|
||||
} data_buffer(const_cast<char *>(data), sizeof(data) - 1);
|
||||
|
||||
std::istream is_data(&data_buffer);
|
||||
f.load(is_data);
|
||||
f.load(is_data, validator);
|
||||
|
||||
auto &cat1 = f.front()["cat_1"];
|
||||
|
||||
@@ -1015,7 +1076,7 @@ save__cat_2.desc
|
||||
|
||||
struct membuf : public std::streambuf
|
||||
{
|
||||
membuf(char *text, size_t length)
|
||||
membuf(char *text, std::size_t length)
|
||||
{
|
||||
this->setg(text, text, text + length);
|
||||
}
|
||||
@@ -1026,7 +1087,6 @@ save__cat_2.desc
|
||||
auto validator = cif::parse_dictionary("test", is_dict);
|
||||
|
||||
cif::file f;
|
||||
f.set_validator(&validator);
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
@@ -1053,14 +1113,14 @@ _cat_2.desc
|
||||
|
||||
struct data_membuf : public std::streambuf
|
||||
{
|
||||
data_membuf(char *text, size_t length)
|
||||
data_membuf(char *text, std::size_t length)
|
||||
{
|
||||
this->setg(text, text, text + length);
|
||||
}
|
||||
} data_buffer(const_cast<char *>(data), sizeof(data) - 1);
|
||||
|
||||
std::istream is_data(&data_buffer);
|
||||
f.load(is_data);
|
||||
f.load(is_data, validator);
|
||||
|
||||
auto &cat1 = f.front()["cat_1"];
|
||||
auto &cat2 = f.front()["cat_2"];
|
||||
@@ -1218,7 +1278,7 @@ save__cat_2.parent_id3
|
||||
|
||||
struct membuf : public std::streambuf
|
||||
{
|
||||
membuf(char *text, size_t length)
|
||||
membuf(char *text, std::size_t length)
|
||||
{
|
||||
this->setg(text, text, text + length);
|
||||
}
|
||||
@@ -1229,7 +1289,6 @@ save__cat_2.parent_id3
|
||||
auto validator = cif::parse_dictionary("test", is_dict);
|
||||
|
||||
cif::file f;
|
||||
f.set_validator(&validator);
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
@@ -1266,14 +1325,14 @@ _cat_2.parent_id3
|
||||
|
||||
struct data_membuf : public std::streambuf
|
||||
{
|
||||
data_membuf(char *text, size_t length)
|
||||
data_membuf(char *text, std::size_t length)
|
||||
{
|
||||
this->setg(text, text, text + length);
|
||||
}
|
||||
} data_buffer(const_cast<char *>(data), sizeof(data) - 1);
|
||||
|
||||
std::istream is_data(&data_buffer);
|
||||
f.load(is_data);
|
||||
f.load(is_data, validator);
|
||||
|
||||
auto &cat1 = f.front()["cat_1"];
|
||||
auto &cat2 = f.front()["cat_2"];
|
||||
@@ -1439,7 +1498,7 @@ cat_2 3 cat_2:cat_1:3
|
||||
|
||||
struct membuf : public std::streambuf
|
||||
{
|
||||
membuf(char *text, size_t length)
|
||||
membuf(char *text, std::size_t length)
|
||||
{
|
||||
this->setg(text, text, text + length);
|
||||
}
|
||||
@@ -1450,7 +1509,6 @@ cat_2 3 cat_2:cat_1:3
|
||||
auto validator = cif::parse_dictionary("test", is_dict);
|
||||
|
||||
cif::file f;
|
||||
f.set_validator(&validator);
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
@@ -1480,14 +1538,14 @@ _cat_2.parent_id3
|
||||
|
||||
struct data_membuf : public std::streambuf
|
||||
{
|
||||
data_membuf(char *text, size_t length)
|
||||
data_membuf(char *text, std::size_t length)
|
||||
{
|
||||
this->setg(text, text, text + length);
|
||||
}
|
||||
} data_buffer(const_cast<char *>(data), sizeof(data) - 1);
|
||||
|
||||
std::istream is_data(&data_buffer);
|
||||
f.load(is_data);
|
||||
f.load(is_data, validator);
|
||||
|
||||
auto &cat1 = f.front()["cat_1"];
|
||||
auto &cat2 = f.front()["cat_2"];
|
||||
@@ -1679,7 +1737,7 @@ cat_2 1 cat_2:cat_1:1
|
||||
|
||||
struct membuf : public std::streambuf
|
||||
{
|
||||
membuf(char *text, size_t length)
|
||||
membuf(char *text, std::size_t length)
|
||||
{
|
||||
this->setg(text, text, text + length);
|
||||
}
|
||||
@@ -1690,7 +1748,6 @@ cat_2 1 cat_2:cat_1:1
|
||||
auto validator = cif::parse_dictionary("test", is_dict);
|
||||
|
||||
cif::file f;
|
||||
f.set_validator(&validator);
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
@@ -1720,14 +1777,14 @@ _cat_2.parent_id_2
|
||||
|
||||
struct data_membuf : public std::streambuf
|
||||
{
|
||||
data_membuf(char *text, size_t length)
|
||||
data_membuf(char *text, std::size_t length)
|
||||
{
|
||||
this->setg(text, text, text + length);
|
||||
}
|
||||
} data_buffer(const_cast<char *>(data), sizeof(data) - 1);
|
||||
|
||||
std::istream is_data(&data_buffer);
|
||||
f.load(is_data);
|
||||
f.load(is_data, validator);
|
||||
|
||||
// auto &cat1 = f.front()["cat_1"];
|
||||
auto &cat2 = f.front()["cat_2"];
|
||||
@@ -2075,7 +2132,7 @@ cat_2 1 '_cat_2.num' '_cat_3.num' cat_3
|
||||
|
||||
struct membuf : public std::streambuf
|
||||
{
|
||||
membuf(char *text, size_t length)
|
||||
membuf(char *text, std::size_t length)
|
||||
{
|
||||
this->setg(text, text, text + length);
|
||||
}
|
||||
@@ -2086,7 +2143,6 @@ cat_2 1 '_cat_2.num' '_cat_3.num' cat_3
|
||||
auto validator = cif::parse_dictionary("test", is_dict);
|
||||
|
||||
cif::file f;
|
||||
f.set_validator(&validator);
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
@@ -2121,14 +2177,14 @@ _cat_3.num
|
||||
|
||||
struct data_membuf : public std::streambuf
|
||||
{
|
||||
data_membuf(char *text, size_t length)
|
||||
data_membuf(char *text, std::size_t length)
|
||||
{
|
||||
this->setg(text, text, text + length);
|
||||
}
|
||||
} data_buffer(const_cast<char *>(data), sizeof(data) - 1);
|
||||
|
||||
std::istream is_data(&data_buffer);
|
||||
f.load(is_data);
|
||||
f.load(is_data, validator);
|
||||
|
||||
auto &cat1 = f.front()["cat_1"];
|
||||
auto &cat2 = f.front()["cat_2"];
|
||||
@@ -2360,7 +2416,7 @@ cat_2 1 '_cat_2.num' '_cat_3.num' cat_3
|
||||
|
||||
struct membuf : public std::streambuf
|
||||
{
|
||||
membuf(char *text, size_t length)
|
||||
membuf(char *text, std::size_t length)
|
||||
{
|
||||
this->setg(text, text, text + length);
|
||||
}
|
||||
@@ -2371,7 +2427,6 @@ cat_2 1 '_cat_2.num' '_cat_3.num' cat_3
|
||||
auto validator = cif::parse_dictionary("test", is_dict);
|
||||
|
||||
cif::file f;
|
||||
f.set_validator(&validator);
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
@@ -2406,14 +2461,14 @@ _cat_3.num
|
||||
|
||||
struct data_membuf : public std::streambuf
|
||||
{
|
||||
data_membuf(char *text, size_t length)
|
||||
data_membuf(char *text, std::size_t length)
|
||||
{
|
||||
this->setg(text, text, text + length);
|
||||
}
|
||||
} data_buffer(const_cast<char *>(data), sizeof(data) - 1);
|
||||
|
||||
std::istream is_data(&data_buffer);
|
||||
f.load(is_data);
|
||||
f.load(is_data, validator);
|
||||
|
||||
auto &cat1 = f.front()["cat_1"];
|
||||
auto &cat2 = f.front()["cat_2"];
|
||||
@@ -2567,11 +2622,11 @@ _cat_3.num
|
||||
// bonded.insert({atom_id_1, atom_id_2});
|
||||
// }
|
||||
|
||||
// for (size_t i = 0; i + 1 < atoms.size(); ++i)
|
||||
// for (std::size_t i = 0; i + 1 < atoms.size(); ++i)
|
||||
// {
|
||||
// auto label_i = atoms[i].labelAtomID();
|
||||
|
||||
// for (size_t j = i + 1; j < atoms.size(); ++j)
|
||||
// for (std::size_t j = i + 1; j < atoms.size(); ++j)
|
||||
// {
|
||||
// auto label_j = atoms[j].labelAtomID();
|
||||
|
||||
@@ -2592,7 +2647,7 @@ _cat_3.num
|
||||
|
||||
// auto &poly = structure.polymers().front();
|
||||
|
||||
// for (size_t i = 0; i + 1 < poly.size(); ++i)
|
||||
// for (std::size_t i = 0; i + 1 < poly.size(); ++i)
|
||||
// {
|
||||
// auto C = poly[i].atomByID("C");
|
||||
// auto N = poly[i + 1].atomByID("N");
|
||||
@@ -2694,7 +2749,7 @@ boo.data_.whatever
|
||||
|
||||
REQUIRE(test1.size() == sizeof(kS) / sizeof(T));
|
||||
|
||||
size_t i = 0;
|
||||
std::size_t i = 0;
|
||||
for (auto r : test1)
|
||||
{
|
||||
auto text = r.get<std::string>("text");
|
||||
@@ -2750,7 +2805,7 @@ There it was!)",
|
||||
|
||||
REQUIRE(test1.size() == sizeof(kS) / sizeof(T));
|
||||
|
||||
size_t i = 0;
|
||||
std::size_t i = 0;
|
||||
for (auto r : test1)
|
||||
{
|
||||
auto text = r.get<std::string>("text");
|
||||
@@ -2957,7 +3012,7 @@ save__cat_1.name
|
||||
|
||||
struct membuf : public std::streambuf
|
||||
{
|
||||
membuf(char *text, size_t length)
|
||||
membuf(char *text, std::size_t length)
|
||||
{
|
||||
this->setg(text, text, text + length);
|
||||
}
|
||||
@@ -2968,7 +3023,6 @@ save__cat_1.name
|
||||
auto validator = cif::parse_dictionary("test", is_dict);
|
||||
|
||||
cif::file f;
|
||||
f.set_validator(&validator);
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
@@ -2984,14 +3038,14 @@ _cat_1.name
|
||||
|
||||
struct data_membuf : public std::streambuf
|
||||
{
|
||||
data_membuf(char *text, size_t length)
|
||||
data_membuf(char *text, std::size_t length)
|
||||
{
|
||||
this->setg(text, text, text + length);
|
||||
}
|
||||
} data_buffer(const_cast<char *>(data), sizeof(data) - 1);
|
||||
|
||||
std::istream is_data(&data_buffer);
|
||||
f.load(is_data);
|
||||
f.load(is_data, validator);
|
||||
|
||||
REQUIRE(f.is_valid());
|
||||
|
||||
@@ -3152,7 +3206,7 @@ save__cat_1.name
|
||||
|
||||
struct membuf : public std::streambuf
|
||||
{
|
||||
membuf(char *text, size_t length)
|
||||
membuf(char *text, std::size_t length)
|
||||
{
|
||||
this->setg(text, text, text + length);
|
||||
}
|
||||
@@ -3163,7 +3217,6 @@ save__cat_1.name
|
||||
auto &validator = cif::validator_factory::instance().construct_validator("test_dict.dic", is_dict);
|
||||
|
||||
cif::file f;
|
||||
f.set_validator(&validator);
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
@@ -3183,26 +3236,28 @@ _cat_1.name
|
||||
|
||||
struct data_membuf : public std::streambuf
|
||||
{
|
||||
data_membuf(char *text, size_t length)
|
||||
data_membuf(char *text, std::size_t length)
|
||||
{
|
||||
this->setg(text, text, text + length);
|
||||
}
|
||||
} data_buffer(const_cast<char *>(data), sizeof(data) - 1);
|
||||
|
||||
std::istream is_data(&data_buffer);
|
||||
f.load(is_data);
|
||||
f.load(is_data, validator);
|
||||
|
||||
REQUIRE(f.is_valid());
|
||||
CHECK(f.is_valid());
|
||||
|
||||
std::stringstream ss;
|
||||
ss << f;
|
||||
|
||||
cif::file f2(ss);
|
||||
REQUIRE(f2.is_valid());
|
||||
REQUIRE(f2.empty() == false);
|
||||
f2.front().load_dictionary();
|
||||
CHECK(f2.is_valid());
|
||||
|
||||
auto &audit_conform = f2.front()["audit_conform"];
|
||||
REQUIRE(audit_conform.front()["dict_name"].as<std::string>() == "test_dict.dic");
|
||||
REQUIRE(audit_conform.front()["dict_version"].as<float>() == 1.0);
|
||||
CHECK(audit_conform.front()["dict_name"].as<std::string>() == "test_dict.dic");
|
||||
CHECK(audit_conform.front()["dict_version"].as<float>() == 1.0);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
@@ -3259,7 +3314,7 @@ save__cat_1.id_2
|
||||
|
||||
struct membuf : public std::streambuf
|
||||
{
|
||||
membuf(char *text, size_t length)
|
||||
membuf(char *text, std::size_t length)
|
||||
{
|
||||
this->setg(text, text, text + length);
|
||||
}
|
||||
@@ -3270,7 +3325,6 @@ save__cat_1.id_2
|
||||
auto validator = cif::parse_dictionary("test", is_dict);
|
||||
|
||||
cif::file f;
|
||||
f.set_validator(&validator);
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
@@ -3288,14 +3342,14 @@ _cat_1.id_2
|
||||
|
||||
struct data_membuf : public std::streambuf
|
||||
{
|
||||
data_membuf(char *text, size_t length)
|
||||
data_membuf(char *text, std::size_t length)
|
||||
{
|
||||
this->setg(text, text, text + length);
|
||||
}
|
||||
} data_buffer(const_cast<char *>(data), sizeof(data) - 1);
|
||||
|
||||
std::istream is_data(&data_buffer);
|
||||
f.load(is_data);
|
||||
f.load(is_data, validator);
|
||||
|
||||
auto &cat1 = f.front()["cat_1"];
|
||||
|
||||
@@ -3434,7 +3488,7 @@ TEST_CASE("compound_test_1")
|
||||
cif::compound_factory::instance().push_dictionary(gTestDir / "REA_v2.cif");
|
||||
auto compound = cif::compound_factory::instance().create("REA_v2");
|
||||
REQUIRE(compound != nullptr);
|
||||
REQUIRE(compound->id() == "REA_v2");
|
||||
REQUIRE(cif::iequals(compound->id(), "REA_v2"));
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
@@ -3472,7 +3526,7 @@ ATOM 7 CD PRO A 1 15.762 13.216 43.724 1.00 30.71 C)"
|
||||
|
||||
struct membuf : public std::streambuf
|
||||
{
|
||||
membuf(char *text, size_t length)
|
||||
membuf(char *text, std::size_t length)
|
||||
{
|
||||
this->setg(text, text, text + length);
|
||||
}
|
||||
|
||||
@@ -32,11 +32,11 @@
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
cif::file operator""_cf(const char *text, size_t length)
|
||||
cif::file operator""_cf(const char *text, std::size_t length)
|
||||
{
|
||||
struct membuf : public std::streambuf
|
||||
{
|
||||
membuf(char *text, size_t length)
|
||||
membuf(char *text, std::size_t length)
|
||||
{
|
||||
this->setg(text, text, text + length);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user