Merge branch 'develop' of github.com:PDB-REDO/libcifpp into develop

This commit is contained in:
Maarten L. Hekkelman
2026-03-04 20:28:12 +01:00
7 changed files with 48 additions and 36 deletions

View File

@@ -374,7 +374,7 @@ class atom
/// Return true if this atom is an alternate
[[nodiscard]] bool is_alternate() const
{
if (auto alt_id = get_label_alt_id(); alt_id.empty())
if (auto alt_id = get_property_value("label_alt_id"); alt_id.empty())
return false;
return true;
}

View File

@@ -61,12 +61,6 @@
namespace cif
{
// --------------------------------------------------------------------
/// \brief Our value for Pi
const double
kPI = std::numbers::pi;
// --------------------------------------------------------------------
/**
* @brief A stripped down quaternion implementation, based on boost::math::quaternion
@@ -809,7 +803,7 @@ constexpr auto angle(const point_type<F> &p1, const point_type<F> &p2, const poi
point_type<F> v1 = p1 - p2;
point_type<F> v2 = p3 - p2;
return std::acos(dot_product(v1, v2) / (v1.length() * v2.length())) * 180 / kPI;
return std::acos(dot_product(v1, v2) / (v1.length() * v2.length())) * 180 / std::numbers::pi_v<F>;
}
/// \brief return the dihedral angle in degrees for the four points @a p1, @a p2, @a p3 and @a p4
@@ -836,7 +830,7 @@ constexpr auto dihedral_angle(const point_type<F> &p1, const point_type<F> &p2,
u = dot_product(p, x) / std::sqrt(u);
v = dot_product(p, y) / std::sqrt(v);
if (u != 0 or v != 0)
result = std::atan2(v, u) * static_cast<F>(180 / kPI);
result = std::atan2(v, u) * static_cast<F>(180 / std::numbers::pi_v<F>);
}
return result;
@@ -882,7 +876,7 @@ point nudge(point p, float offset);
quaternion construct_from_angle_axis(float angle, point axis);
/// \brief Return a tuple of an angle and an axis for quaternion @a q
std::tuple<double, point> quaternion_to_angle_axis(quaternion q);
std::tuple<float, point> quaternion_to_angle_axis(quaternion q);
/// @brief Given four points and an angle, return the quaternion required to rotate
/// point p4 along the p2-p3 axis and around point p3 to obtain the required within
@@ -924,7 +918,7 @@ class spherical_dots
constexpr static int P = 2 * N * 1;
/// \brief the *weight* of the fibonacci sphere
constexpr static double W = (4 * kPI) / P;
constexpr static double W = (4 * std::numbers::pi) / P;
/// \brief the internal storage type
using array_type = typename std::array<point, P>;
@@ -964,7 +958,7 @@ class spherical_dots
for (int32_t i = -N; i <= N; ++i)
{
double lat = std::asin((2.0 * i) / P);
double lon = std::fmod(i, kGoldenRatio) * 2 * kPI / kGoldenRatio;
double lon = std::fmod(i, kGoldenRatio) * 2 * std::numbers::pi / kGoldenRatio;
p->m_x = std::sin(lon) * std::cos(lat);
p->m_y = std::cos(lon) * std::cos(lat);

View File

@@ -490,7 +490,7 @@ float monomer::kappa() const
{
double ckap = cosinus_angle(CAlpha().get_location(), prevPrev.CAlpha().get_location(), nextNext.CAlpha().get_location(), CAlpha().get_location());
double skap = std::sqrt(1 - ckap * ckap);
result = static_cast<float>(std::atan2(skap, ckap) * 180 / kPI);
result = static_cast<float>(std::atan2(skap, ckap) * 180 / std::numbers::pi_v<float>);
}
}
}
@@ -1298,31 +1298,31 @@ void structure::load_data()
// place atoms in residues
using key_type = std::tuple<std::string, int, std::string>;
using key_type = std::tuple<std::string, int, std::string, std::string>;
std::map<key_type, residue *> resMap;
for (auto &poly : m_polymers)
{
for (auto &res : poly)
resMap[{ res.get_asym_id(), res.get_seq_id(), res.get_pdb_seq_num() }] = &res;
resMap[{ res.get_asym_id(), res.get_seq_id(), res.get_pdb_seq_num(), res.get_compound_id() }] = &res;
}
for (auto &res : m_non_polymers)
resMap[{ res.get_asym_id(), res.get_seq_id(), res.get_pdb_seq_num() }] = &res;
resMap[{ res.get_asym_id(), res.get_seq_id(), res.get_pdb_seq_num(), res.get_compound_id() }] = &res;
std::set<std::string> sugars;
for (auto &branch : m_branches)
{
for (auto &sugar : branch)
{
resMap[{ sugar.get_asym_id(), sugar.get_seq_id(), sugar.get_pdb_seq_num() }] = &sugar;
resMap[{ sugar.get_asym_id(), sugar.get_seq_id(), sugar.get_pdb_seq_num(), sugar.get_compound_id() }] = &sugar;
sugars.insert(sugar.get_compound_id());
}
}
for (auto &atom : m_atoms)
{
key_type k(atom.get_label_asym_id(), atom.get_label_seq_id(), atom.get_auth_seq_id());
key_type k(atom.get_label_asym_id(), atom.get_label_seq_id(), atom.get_auth_seq_id(), atom.get_label_comp_id());
auto ri = resMap.find(k);
if (ri == resMap.end())

View File

@@ -73,7 +73,7 @@ quaternion_type<T> normalize(quaternion_type<T> q)
quaternion construct_from_angle_axis(float angle, point axis)
{
angle = static_cast<float>((angle * kPI / 180) / 2);
angle = (angle * std::numbers::pi_v<float> / 180) / 2;
auto s = std::sin(angle);
auto c = std::cos(angle);
@@ -86,14 +86,14 @@ quaternion construct_from_angle_axis(float angle, point axis)
static_cast<float>(s * axis.m_z) });
}
std::tuple<double, point> quaternion_to_angle_axis(quaternion q)
std::tuple<float, point> quaternion_to_angle_axis(quaternion q)
{
if (q.get_a() > 1)
q = normalize(q);
// angle:
double angle = 2 * std::acos(q.get_a());
angle = angle * 180 / kPI;
float angle = 2 * std::acos(q.get_a());
angle = angle * 180 / std::numbers::pi_v<float>;
// axis:
float s = std::sqrt(1 - q.get_a() * q.get_a());

View File

@@ -75,29 +75,29 @@ cell::cell(const datablock &db)
void cell::init()
{
auto alpha = (m_alpha * kPI) / 180;
auto beta = (m_beta * kPI) / 180;
auto gamma = (m_gamma * kPI) / 180;
auto alpha = (m_alpha * std::numbers::pi_v<float>) / 180;
auto beta = (m_beta * std::numbers::pi_v<float>) / 180;
auto gamma = (m_gamma * std::numbers::pi_v<float>) / 180;
auto alpha_star = std::acos((std::cos(gamma) * std::cos(beta) - std::cos(alpha)) / (std::sin(beta) * std::sin(gamma)));
m_orthogonal = identity_matrix(3);
m_orthogonal(0, 0) = static_cast<float>(m_a);
m_orthogonal(0, 1) = static_cast<float>(m_b * std::cos(gamma));
m_orthogonal(0, 2) = static_cast<float>(m_c * std::cos(beta));
m_orthogonal(1, 1) = static_cast<float>(m_b * std::sin(gamma));
m_orthogonal(1, 2) = static_cast<float>(-m_c * std::sin(beta) * std::cos(alpha_star));
m_orthogonal(2, 2) = static_cast<float>(m_c * std::sin(beta) * std::sin(alpha_star));
m_orthogonal(0, 0) = m_a;
m_orthogonal(0, 1) = m_b * std::cos(gamma);
m_orthogonal(0, 2) = m_c * std::cos(beta);
m_orthogonal(1, 1) = m_b * std::sin(gamma);
m_orthogonal(1, 2) = m_c * std::sin(beta) * std::cos(alpha_star);
m_orthogonal(2, 2) = m_c * std::sin(beta) * std::sin(alpha_star);
m_fractional = inverse(m_orthogonal);
}
float cell::get_volume() const
{
auto alpha = (m_alpha * kPI) / 180;
auto beta = (m_beta * kPI) / 180;
auto gamma = (m_gamma * kPI) / 180;
auto alpha = (m_alpha * std::numbers::pi_v<float>) / 180;
auto beta = (m_beta * std::numbers::pi_v<float>) / 180;
auto gamma = (m_gamma * std::numbers::pi_v<float>) / 180;
auto cos_alpha = std::cos(alpha);
auto cos_beta = std::cos(beta);

View File

@@ -26,6 +26,7 @@
#include "test-main.hpp"
#include <catch2/catch_test_macros.hpp>
#include <cif++/cif++.hpp>
// --------------------------------------------------------------------
@@ -433,6 +434,23 @@ TEST_CASE("remove_residue_1")
CHECK_NOTHROW(s.validate_atoms());
}
// --------------------------------------------------------------------
TEST_CASE("test_alternates_1")
{
using namespace cif::literals;
const std::filesystem::path example(gTestDir / ".." / "examples" / "1cbs.cif.gz");
cif::file file(example.string());
auto &db = file.front();
cif::mm::structure s(file);
for (auto atom : s.atoms())
CHECK_FALSE(atom.is_alternate());
}
// --------------------------------------------------------------------
// Tests for structure_open_options

View File

@@ -117,7 +117,7 @@ TEST_CASE("t2")
cif::point xp = cif::cross_product(p[1] - p[0], p[2] - p[0]);
auto q = cif::construct_from_angle_axis(45, xp); // mmcif::Normalize(Quaternion{45 * mmcif::kPI / 180, xp.mX, xp.mY, xp.mZ});
auto q = cif::construct_from_angle_axis(45, xp);
auto &&[angle, axis] = cif::quaternion_to_angle_axis(q);
@@ -134,7 +134,7 @@ TEST_CASE("t3")
cif::point xp = cif::cross_product(p[1] - p[0], p[2] - p[0]);
auto q = cif::construct_from_angle_axis(45, xp); // mmcif::Normalize(Quaternion{45 * mmcif::kPI / 180, xp.mX, xp.mY, xp.mZ});
auto q = cif::construct_from_angle_axis(45, xp);
auto v = p[1];
v -= p[0];