Commit 9485bec2 by Maarten L. Hekkelman

Moved symmetry back into libcifpp

parent 4b759e73
......@@ -66,6 +66,19 @@ if(UNIX)
option(CIFPP_INSTALL_UPDATE_SCRIPT "Install the script to update CCD and dictionary files" OFF)
endif()
# When CCP4 is sourced in the environment, we can recreate the symmetry operations table
if(EXISTS "$ENV{CCP4}")
if(EXISTS "$ENV{CLIBD}/syminfo.lib")
option(PDBXPP_RECREATE_SYMOP_DATA "Recreate SymOp data table in case it is out of date" ON)
else()
set(PDBXPP_RECREATE_SYMOP_DATA OFF)
message(WARNING "Symop data table recreation requested, but file syminfo.lib was not found in $ENV{CLIBD}")
endif()
else()
set(PDBXPP_RECREATE_SYMOP_DATA OFF)
message("Not trying to recreate symop_table_data.hpp since CCP4 is not defined")
endif()
# Unit tests
option(ENABLE_TESTING "Build test exectuables" OFF)
......@@ -143,6 +156,22 @@ list(APPEND CIFPP_REQUIRED_LIBRARIES ${STDCPPATOMIC_LIBRARY})
include(VersionString)
write_version_header("LibCIFPP")
# SymOp data table
if(PDBXPP_RECREATE_SYMOP_DATA)
# The tool to create the table
add_executable(symop-map-generator "${PROJECT_SOURCE_DIR}/tools/symop-map-generator.cpp")
add_custom_command(
OUTPUT ${PROJECT_SOURCE_DIR}/src/symop_table_data.hpp
COMMAND $<TARGET_FILE:symop-map-generator> $ENV{CLIBD}/syminfo.lib ${PROJECT_SOURCE_DIR}/src/symop_table_data.hpp
)
add_custom_target(
OUTPUT ${PROJECT_SOURCE_DIR}/src/symop_table_data.hpp
DEPENDS symop-map-generator "$ENV{CLIBD}/syminfo.lib"
)
endif()
# Sources
set(project_sources
${PROJECT_SOURCE_DIR}/src/category.cpp
......@@ -160,6 +189,7 @@ set(project_sources
${PROJECT_SOURCE_DIR}/src/atom_type.cpp
${PROJECT_SOURCE_DIR}/src/compound.cpp
${PROJECT_SOURCE_DIR}/src/point.cpp
${PROJECT_SOURCE_DIR}/src/symmetry.cpp
)
set(project_headers
......@@ -181,9 +211,10 @@ set(project_headers
${PROJECT_SOURCE_DIR}/include/cif++/atom_type.hpp
${PROJECT_SOURCE_DIR}/include/cif++/compound.hpp
${PROJECT_SOURCE_DIR}/include/cif++/point.hpp
${PROJECT_SOURCE_DIR}/include/cif++/symmetry.hpp
)
add_library(cifpp ${project_sources} ${project_headers})
add_library(cifpp ${project_sources} ${project_headers} ${PROJECT_SOURCE_DIR}/src/symop_table_data.hpp)
add_library(cifpp::cifpp ALIAS cifpp)
set_target_properties(cifpp PROPERTIES POSITION_INDEPENDENT_CODE ON)
......
/*-
* SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2020 NKI/AVL, Netherlands Cancer Institute
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#pragma once
#include <array>
#include <cstdint>
#include <string>
namespace cif
{
// --------------------------------------------------------------------
enum class space_group_name
{
full,
xHM,
Hall
};
struct space_group
{
const char *name;
const char *xHM;
const char *Hall;
int nr;
};
// extern const Spacegroup kSpaceGroups[];
// extern const std::size_t kNrOfSpaceGroups;
// --------------------------------------------------------------------
struct symop_data
{
constexpr symop_data(const std::array<int, 15> &data)
: m_packed((data[0] & 0x03ULL) << 34 bitor
(data[1] & 0x03ULL) << 32 bitor
(data[2] & 0x03ULL) << 30 bitor
(data[3] & 0x03ULL) << 28 bitor
(data[4] & 0x03ULL) << 26 bitor
(data[5] & 0x03ULL) << 24 bitor
(data[6] & 0x03ULL) << 22 bitor
(data[7] & 0x03ULL) << 20 bitor
(data[8] & 0x03ULL) << 18 bitor
(data[9] & 0x07ULL) << 15 bitor
(data[10] & 0x07ULL) << 12 bitor
(data[11] & 0x07ULL) << 9 bitor
(data[12] & 0x07ULL) << 6 bitor
(data[13] & 0x07ULL) << 3 bitor
(data[14] & 0x07ULL) << 0)
{
}
bool operator==(const symop_data &rhs) const
{
return m_packed == rhs.m_packed;
}
std::array<int, 15> data() const
{
return {
static_cast<int>(m_packed >> 34) bitand 0x03,
static_cast<int>(m_packed >> 32) bitand 0x03,
static_cast<int>(m_packed >> 30) bitand 0x03,
static_cast<int>(m_packed >> 28) bitand 0x03,
static_cast<int>(m_packed >> 26) bitand 0x03,
static_cast<int>(m_packed >> 24) bitand 0x03,
static_cast<int>(m_packed >> 22) bitand 0x03,
static_cast<int>(m_packed >> 20) bitand 0x03,
static_cast<int>(m_packed >> 18) bitand 0x03,
static_cast<int>(m_packed >> 15) bitand 0x07,
static_cast<int>(m_packed >> 12) bitand 0x07,
static_cast<int>(m_packed >> 9) bitand 0x07,
static_cast<int>(m_packed >> 6) bitand 0x07,
static_cast<int>(m_packed >> 3) bitand 0x07,
static_cast<int>(m_packed >> 0) bitand 0x07,
};
}
private:
friend struct symop_datablock;
const uint64_t kPackMask = (~0ULL >> (64 - 36));
symop_data(uint64_t v)
: m_packed(v bitand kPackMask)
{
}
uint64_t m_packed;
};
struct symop_datablock
{
constexpr symop_datablock(int spacegroup, int rotational_number, const std::array<int, 15> &rt_data)
: m_v((spacegroup & 0xffffULL) << 48 bitor
(rotational_number & 0xffULL) << 40 bitor
symop_data(rt_data).m_packed)
{
}
uint16_t spacegroup() const { return m_v >> 48; }
symop_data symop() const { return symop_data(m_v); }
uint8_t rotational_number() const { return (m_v >> 40) bitand 0xff; }
private:
uint64_t m_v;
};
static_assert(sizeof(symop_datablock) == sizeof(uint64_t), "Size of symop_data is wrong");
// extern const symop_data_block kSymopNrTable[];
// extern const std::size_t kSymopNrTableSize;
// --------------------------------------------------------------------
int get_space_group_number(std::string spacegroup); // alternative for clipper's parsing code, using space_group_name::full
int get_space_group_number(std::string spacegroup, space_group_name type); // alternative for clipper's parsing code
} // namespace cif
/*-
* SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2020 NKI/AVL, Netherlands Cancer Institute
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <atomic>
#include <mutex>
#include <cif++/symmetry.hpp>
#include "./symop_table_data.hpp"
namespace cif
{
// --------------------------------------------------------------------
// Unfortunately, clipper has a different numbering scheme than PDB
// for rotation numbers. So we created a table to map those.
// Perhaps a bit over the top, but hey....
// --------------------------------------------------------------------
int get_space_group_number(std::string spacegroup)
{
if (spacegroup == "P 21 21 2 A")
spacegroup = "P 21 21 2 (a)";
else if (spacegroup.empty())
throw std::runtime_error("No spacegroup, cannot continue");
int result = 0;
const size_t N = kNrOfSpaceGroups;
int32_t L = 0, R = static_cast<int32_t>(N - 1);
while (L <= R)
{
int32_t i = (L + R) / 2;
int d = spacegroup.compare(kSpaceGroups[i].name);
if (d > 0)
L = i + 1;
else if (d < 0)
R = i - 1;
else
{
result = kSpaceGroups[i].nr;
break;
}
}
// not found, see if we can find a match based on xHM name
if (result == 0)
{
for (size_t i = 0; i < kNrOfSpaceGroups; ++i)
{
auto& sp = kSpaceGroups[i];
if (sp.xHM == spacegroup)
{
result = sp.nr;
break;
}
}
}
if (result == 0)
throw std::runtime_error("Spacegroup name " + spacegroup + " was not found in table");
return result;
}
// --------------------------------------------------------------------
int get_space_group_number(std::string spacegroup, space_group_name type)
{
if (spacegroup == "P 21 21 2 A")
spacegroup = "P 21 21 2 (a)";
else if (spacegroup.empty())
throw std::runtime_error("No spacegroup, cannot continue");
int result = 0;
if (type == space_group_name::full)
{
const size_t N = kNrOfSpaceGroups;
int32_t L = 0, R = static_cast<int32_t>(N - 1);
while (L <= R)
{
int32_t i = (L + R) / 2;
int d = spacegroup.compare(kSpaceGroups[i].name);
if (d > 0)
L = i + 1;
else if (d < 0)
R = i - 1;
else
{
result = kSpaceGroups[i].nr;
break;
}
}
}
else if (type == space_group_name::xHM)
{
for (auto &sg : kSpaceGroups)
{
if (sg.xHM == spacegroup)
{
result = sg.nr;
break;
}
}
}
else
{
for (auto &sg : kSpaceGroups)
{
if (sg.Hall == spacegroup)
{
result = sg.nr;
break;
}
}
}
// not found, see if we can find a match based on xHM name
if (result == 0)
throw std::runtime_error("Spacegroup name " + spacegroup + " was not found in table");
return result;
}
}
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -358,12 +358,12 @@ int main(int argc, char* const argv[])
// and $CLIBD/syminfo.lib using symop-map-generator,
// part of the PDB-REDO suite of programs.
#include <cif++/structure/Symmetry.hpp>
#include <cif++/symmetry.hpp>
namespace mmcif
namespace cif
{
const Spacegroup kSpaceGroups[] =
const space_group kSpaceGroups[] =
{
)";
......@@ -397,9 +397,9 @@ const Spacegroup kSpaceGroups[] =
out << R"(
};
const size_t kNrOfSpaceGroups = sizeof(kSpaceGroups) / sizeof(Spacegroup);
const size_t kNrOfSpaceGroups = sizeof(kSpaceGroups) / sizeof(space_group);
const SymopDataBlock kSymopNrTable[] = {
const symop_datablock kSymopNrTable[] = {
)" << std::endl;
int spacegroupNr = 0;
......@@ -421,7 +421,7 @@ const SymopDataBlock kSymopNrTable[] = {
out << R"(};
const size_t kSymopNrTableSize = sizeof(kSymopNrTable) / sizeof(SymopDataBlock);
const size_t kSymopNrTableSize = sizeof(kSymopNrTable) / sizeof(symop_datablock);
} // namespace mmcif
)" << std::endl;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment