[med-svn] [Git][med-team/dssp][upstream] New upstream version 4.6.0
Maarten L. Hekkelman (@mhekkel-guest)
gitlab at salsa.debian.org
Tue Mar 24 10:01:00 GMT 2026
Maarten L. Hekkelman pushed to branch upstream at Debian Med / dssp
Commits:
a41ec052 by Maarten L. Hekkelman at 2026-03-24T10:51:28+01:00
New upstream version 4.6.0
- - - - -
17 changed files:
- + .clang-format
- + .clang-tidy
- .github/workflows/cmake-multi-platform.yml
- CMakeLists.txt
- changelog
- cmake/revision.hpp.in
- libdssp/VERSION
- libdssp/include/dssp.hpp
- libdssp/src/dssp-io.cpp
- libdssp/src/dssp.cpp
- python-module/CMakeLists.txt
- python-module/dssp-python-plugin.cpp
- src/mkdssp.cpp
- test/CMakeLists.txt
- + test/test_numpy2_compat.py
- test/unit-test-dssp.cpp
- tools/depends.cmd
Changes:
=====================================
.clang-format
=====================================
@@ -0,0 +1,22 @@
+BasedOnStyle: LLVM
+UseTab: AlignWithSpaces
+IndentWidth: 4
+TabWidth: 4
+BreakBeforeBraces: Allman
+ColumnLimit: 0
+NamespaceIndentation: Inner
+FixNamespaceComments: true
+AccessModifierOffset: -2
+AllowShortCaseLabelsOnASingleLine: true
+IndentCaseLabels: true
+BreakConstructorInitializers: BeforeComma
+BraceWrapping:
+ BeforeLambdaBody: false
+AlignAfterOpenBracket: DontAlign
+Cpp11BracedListStyle: false
+IncludeBlocks: Regroup
+LambdaBodyIndentation: Signature
+AllowShortLambdasOnASingleLine: Inline
+EmptyLineBeforeAccessModifier: LogicalBlock
+IndentPPDirectives: AfterHash
+PPIndentWidth: 1
=====================================
.clang-tidy
=====================================
@@ -0,0 +1,18 @@
+Checks: '-*,
+ bugprone-*,
+ -bugprone-easily-swappable-parameters,
+ cert-*,
+ modernize*,
+ -modernize-use-trailing-return-type,
+ -modernize-avoid-c-arrays,
+ -modernize-use-designated-initializers,
+ performance
+ '
+
+# HeaderFilterRegex: '.*'
+ExcludeHeaderFilterRegex: 'Eigen|Eigen/Eigenvalues|eigen3/Eigen/Eigenvalues|sqlite3.h'
+CheckOptions:
+ - key: bugprone-narrowing-conversions.WarnOnIntegerNarrowingConversion
+ value: false
+ - key: bugprone-narrowing-conversions.WarnOnIntegerToFloatingPointNarrowingConversion
+ value: false
=====================================
.github/workflows/cmake-multi-platform.yml
=====================================
@@ -6,6 +6,10 @@ on:
pull_request:
branches: [ "trunk" ]
+env:
+ # Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.)
+ BUILD_TYPE: Release
+
jobs:
build:
runs-on: ${{ matrix.os }}
@@ -25,7 +29,7 @@ jobs:
cpp_compiler: clang++
steps:
- - uses: actions/checkout at v3
+ - uses: actions/checkout at v6
- name: Set reusable strings
id: strings
@@ -35,17 +39,17 @@ jobs:
- name: Install Catch2 Ubuntu
if: matrix.os == 'ubuntu-latest'
run: >
- sudo apt-get update && sudo apt-get install catch2 libpython3-all-dev libboost1.83-all-dev
+ sudo apt-get update && sudo apt-get install catch2 libpython3-all-dev
- name: setup python
- uses: actions/setup-python at v5
+ uses: actions/setup-python at v6
with:
python-version: ${{ matrix.python-version }}
- name: Install Catch2 macOS
if: matrix.os == 'macos-latest'
run: >
- brew install catch2 boost-python3
+ brew install catch2
- name: Install dependencies Window
if: matrix.os == 'windows-latest'
@@ -60,7 +64,8 @@ jobs:
-DBUILD_TESTING=ON
-DBUILD_PYTHON_MODULE=ON
-S ${{ github.workspace }}
-
+ -DCMAKE_INSTALL_PREFIX=${{github.workspace}}/local
+
- name: Build
run: cmake --build ${{ steps.strings.outputs.build-output-dir }} --config Release
=====================================
CMakeLists.txt
=====================================
@@ -93,13 +93,6 @@ if(MSVC)
# make msvc standards compliant...
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()
- set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
- endif()
endif()
# Create a revision file, containing the current git version info
@@ -124,15 +117,15 @@ CPMFindPackage(
GIT_TAG v1.4.2
EXCLUDE_FROM_ALL YES)
-# CPMFindPackage does not pass on variables set with set_and_check
-# Working around this here
-find_package(cifpp 9 QUIET)
+# No longer using CPM for libcifpp. It is now simply required to install it first.
+find_package(cifpp 10.0.1 QUIET)
-if(NOT cifpp_FOUND)
+if(NOT (cifpp_FOUND OR TARGET cifpp))
+ # message(FATAL_ERROR "Could not find libcifpp. Please make sure you install libcifpp first, code can be found at https://github.com/PDB-REDO/libcifpp")
CPMAddPackage(
NAME cifpp
- GIT_REPOSITORY https://github.com/pdb-redo/libcifpp.git
- GIT_TAG v9.0.0
+ GIT_REPOSITORY "https://github.com/PDB-REDO/libcifpp"
+ GIT_TAG v10.0.1
EXCLUDE_FROM_ALL YES)
endif()
=====================================
changelog
=====================================
@@ -1,3 +1,10 @@
+Version 4.6.0
+- Using new libcifpp version 10.0
+
+Version 4.5.8
+- Using newer version of Boost for the python plugin,
+ this was needed to be able to use Numpy >= 2.x
+
Version 4.5.7
- Fix for unit-test in Debian repository
=====================================
cmake/revision.hpp.in
=====================================
@@ -96,6 +96,7 @@ class version_info : public version_info_base
public:
using implementation_type = T;
+ // NOLINTNEXTLINE
version_info(const char *name, const char *version, int build_number, const char *git_tag, const char *revision_date, bool is_main)
: version_info_base(name, version, build_number, git_tag, revision_date, is_main)
{
@@ -118,4 +119,4 @@ const class version_info_ at IDENT_PREFIX@impl : public version_info_v1_1::version_
: version_info(k at VAR_PREFIX@ProjectName, k at VAR_PREFIX@VersionNumber, k at VAR_PREFIX@BuildNumber, k at VAR_PREFIX@RevisionGitTag, k at VAR_PREFIX@RevisionDate, @BOOL_IS_MAIN@)
{
}
-} s_version_info_ at IDENT_PREFIX@instance;
+} s_version_info_ at IDENT_PREFIX@instance; // NOLINT
=====================================
libdssp/VERSION
=====================================
@@ -1 +1 @@
-4.5.7
\ No newline at end of file
+4.6.0
\ No newline at end of file
=====================================
libdssp/include/dssp.hpp
=====================================
@@ -29,9 +29,11 @@
/// \file DSSP.hpp
/// Calculate DSSP-like secondary structure information.
-#include <cif++.hpp>
+#include <cif++/cif++.hpp>
#include <filesystem>
+#include <iterator>
+#include <ranges>
class dssp
{
@@ -105,7 +107,7 @@ class dssp
dssp(const dssp &) = delete;
dssp &operator=(const dssp &) = delete;
- statistics get_statistics() const;
+ [[nodiscard]] statistics get_statistics() const;
class iterator;
using res_iterator = typename std::vector<residue>::iterator;
@@ -120,37 +122,37 @@ class dssp
residue_info &operator=(const residue_info &rhs) = default;
explicit operator bool() const { return not empty(); }
- bool empty() const { return m_impl == nullptr; }
+ [[nodiscard]] bool empty() const { return m_impl == nullptr; }
- std::string asym_id() const;
- int seq_id() const;
- std::string alt_id() const;
- std::string compound_id() const;
- char compound_letter() const; // Single letter for residue compound type, or 'X' in case it is not known
+ [[nodiscard]] std::string asym_id() const;
+ [[nodiscard]] int seq_id() const;
+ [[nodiscard]] std::string alt_id() const;
+ [[nodiscard]] std::string compound_id() const;
+ [[nodiscard]] char compound_letter() const; // Single letter for residue compound type, or 'X' in case it is not known
- std::string auth_asym_id() const;
- int auth_seq_id() const;
+ [[nodiscard]] std::string auth_asym_id() const;
+ [[nodiscard]] int auth_seq_id() const;
- std::string pdb_strand_id() const;
- int pdb_seq_num() const;
- std::string pdb_ins_code() const;
+ [[nodiscard]] std::string pdb_strand_id() const;
+ [[nodiscard]] int pdb_seq_num() const;
+ [[nodiscard]] std::string pdb_ins_code() const;
- std::optional<float> alpha() const;
- std::optional<float> kappa() const;
- std::optional<float> phi() const;
- std::optional<float> psi() const;
- std::optional<float> tco() const;
- std::optional<float> omega() const;
+ [[nodiscard]] std::optional<float> alpha() const;
+ [[nodiscard]] std::optional<float> kappa() const;
+ [[nodiscard]] std::optional<float> phi() const;
+ [[nodiscard]] std::optional<float> psi() const;
+ [[nodiscard]] std::optional<float> tco() const;
+ [[nodiscard]] std::optional<float> omega() const;
- bool is_pre_pro() const;
- bool is_cis() const { return std::abs(omega().value_or(360)) < 30.0f; }
+ [[nodiscard]] bool is_pre_pro() const;
+ [[nodiscard]] bool is_cis() const { return std::abs(omega().value_or(360)) < 30.0f; }
- float chiral_volume() const;
+ [[nodiscard]] float chiral_volume() const;
- std::size_t nr_of_chis() const;
- float chi(std::size_t index) const;
+ [[nodiscard]] std::size_t nr_of_chis() const;
+ [[nodiscard]] float chi(std::size_t index) const;
- std::vector<float> chis() const
+ [[nodiscard]] std::vector<float> chis() const
{
std::vector<float> result;
for (size_t i = 0; i < nr_of_chis(); ++i)
@@ -158,34 +160,34 @@ class dssp
return result;
}
- std::tuple<float, float, float> ca_location() const;
+ [[nodiscard]] std::tuple<float, float, float> ca_location() const;
- chain_break_type chain_break() const;
+ [[nodiscard]] chain_break_type chain_break() const;
/// \brief the internal number in DSSP
- int nr() const;
+ [[nodiscard]] int nr() const;
- structure_type type() const;
+ [[nodiscard]] structure_type type() const;
- int ssBridgeNr() const;
+ [[nodiscard]] int ssBridgeNr() const;
- helix_position_type helix(helix_type helixType) const;
+ [[nodiscard]] helix_position_type helix(helix_type helixType) const;
- bool is_alpha_helix_end_before_start() const;
+ [[nodiscard]] bool is_alpha_helix_end_before_start() const;
- bool bend() const;
+ [[nodiscard]] bool bend() const;
- double accessibility() const;
+ [[nodiscard]] double accessibility() const;
/// \brief returns resinfo, ladder and parallel
- std::tuple<residue_info, int, bool> bridge_partner(int i) const;
+ [[nodiscard]] std::tuple<residue_info, int, bool> bridge_partner(int i) const;
- int sheet() const;
- int strand() const;
+ [[nodiscard]] int sheet() const;
+ [[nodiscard]] int strand() const;
/// \brief return resinfo and the energy of the bond
- std::tuple<residue_info, double> acceptor(int i) const;
- std::tuple<residue_info, double> donor(int i) const;
+ [[nodiscard]] std::tuple<residue_info, double> acceptor(int i) const;
+ [[nodiscard]] std::tuple<residue_info, double> donor(int i) const;
/// \brief Simple compare equals
bool operator==(const residue_info &rhs) const
@@ -196,7 +198,7 @@ class dssp
/// \brief Returns \result true if there is a bond between two residues
friend bool test_bond(residue_info const &a, residue_info const &b);
- residue_info next() const;
+ [[nodiscard]] residue_info next() const;
private:
residue_info(residue *res)
@@ -211,17 +213,18 @@ class dssp
{
public:
using iterator_category = std::bidirectional_iterator_tag;
- using value_type = residue_info;
+ using value_type = const residue_info;
using difference_type = std::ptrdiff_t;
using pointer = value_type *;
using reference = value_type &;
+ iterator() = default;
iterator(const iterator &i) = default;
iterator(residue *res);
iterator &operator=(const iterator &i) = default;
- reference operator*() { return m_current; }
- pointer operator->() { return &m_current; }
+ reference operator*() const { return m_current; }
+ pointer operator->() const { return &m_current; }
iterator &operator++();
iterator operator++(int)
@@ -246,17 +249,22 @@ class dssp
residue_info m_current;
};
+ static_assert(std::input_iterator<iterator>);
+
using value_type = residue_info;
// To access residue info by key, i.e. LabelAsymID and LabelSeqID
using key_type = std::tuple<std::string, int>;
- iterator begin() const;
- iterator end() const;
+ [[nodiscard]] iterator begin() const;
+ [[nodiscard]] iterator end() const;
+
+ [[nodiscard]] iterator cbegin() const;
+ [[nodiscard]] iterator cend() const;
residue_info operator[](const key_type &key) const;
- bool empty() const { return begin() == end(); }
+ [[nodiscard]] bool empty() const { return begin() == end(); }
// --------------------------------------------------------------------
// Writing out the data, either in legacy format...
@@ -276,8 +284,10 @@ class dssp
AUTHOR
};
- std::string get_pdb_header_line(pdb_record_type pdb_record) const;
+ [[nodiscard]] std::string get_pdb_header_line(pdb_record_type pdb_record) const;
private:
struct DSSP_impl *m_impl;
};
+
+static_assert(std::ranges::input_range<dssp>);
\ No newline at end of file
=====================================
libdssp/src/dssp-io.cpp
=====================================
@@ -25,15 +25,19 @@
*/
#include "dssp-io.hpp"
+
+#include "cif++/category.hpp"
+#include "cif++/item.hpp"
+#include "cif++/validate.hpp"
#include "revision.hpp"
-#include <cif++.hpp>
+#include <algorithm>
+#include <cif++/cif++.hpp>
#include <cif++/dictionary_parser.hpp>
-
-#include <exception>
-#include <filesystem>
-#include <fstream>
+#include <cif++/row.hpp>
+#include <format>
#include <iostream>
+#include <type_traits>
// --------------------------------------------------------------------
@@ -121,20 +125,20 @@ std::string ResidueToDSSPLine(const dssp::residue_info &info)
if (acceptor)
{
auto d = acceptor.nr() - info.nr();
- NHO[i] = cif::format("{:d},{:3.1f}", d, acceptorE);
+ NHO[i] = std::format("{:d},{:3.1f}", d, acceptorE);
}
if (donor)
{
auto d = donor.nr() - info.nr();
- ONH[i] = cif::format("{:d},{:3.1f}", d, donorE);
+ ONH[i] = std::format("{:d},{:3.1f}", d, donorE);
}
}
// auto ca = residue.atomByID("CA");
auto const &[cax, cay, caz] = residue.ca_location();
- return cif::format("{:5d}{:5d}{:1.1s}{:1.1s} {:1c} {:1c}{:1c}{:1c}{:1c}{:1c}{:1c}{:1c}{:1c}{:1c}{:4d}{:4d}{:1c}{:4.0f} {:>11s}{:>11s}{:>11s}{:>11s} {:6.3f}{:6.1f}{:6.1f}{:6.1f}{:6.1f} {:6.1f} {:6.1f} {:6.1f}",
+ return std::format("{:5d}{:5d}{:1.1s}{:1.1s} {:1c} {:1c}{:1c}{:1c}{:1c}{:1c}{:1c}{:1c}{:1c}{:1c}{:4d}{:4d}{:1c}{:4.0f} {:>11s}{:>11s}{:>11s}{:>11s} {:6.3f}{:6.1f}{:6.1f}{:6.1f}{:6.1f} {:6.1f} {:6.1f} {:6.1f}",
info.nr(), residue.pdb_seq_num(), residue.pdb_ins_code(), residue.pdb_strand_id(), code,
ss, helix[3], helix[0], helix[1], helix[2], bend, chirality, bridgelabel[0], bridgelabel[1],
bp[0], bp[1], sheet, floor(info.accessibility() + 0.5),
@@ -167,40 +171,40 @@ void writeDSSP(const dssp &dssp, std::ostream &os)
<< dssp.get_pdb_header_line(dssp::pdb_record_type::SOURCE) << '.' << std::endl
<< dssp.get_pdb_header_line(dssp::pdb_record_type::AUTHOR) << '.' << std::endl;
- os << cif::format("{:5d}{:3d}{:3d}{:3d}{:3d} TOTAL NUMBER OF RESIDUES, NUMBER OF CHAINS, NUMBER OF SS-BRIDGES(TOTAL,INTRACHAIN,INTERCHAIN) .",
+ os << std::format("{:5d}{:3d}{:3d}{:3d}{:3d} TOTAL NUMBER OF RESIDUES, NUMBER OF CHAINS, NUMBER OF SS-BRIDGES(TOTAL,INTRACHAIN,INTERCHAIN) .",
stats.count.residues, stats.count.chains, stats.count.SS_bridges, stats.count.intra_chain_SS_bridges, (stats.count.SS_bridges - stats.count.intra_chain_SS_bridges))
<< std::endl;
- os << cif::format("{:8.1f} ACCESSIBLE SURFACE OF PROTEIN (ANGSTROM**2) .", stats.accessible_surface) << std::endl;
+ os << std::format("{:8.1f} ACCESSIBLE SURFACE OF PROTEIN (ANGSTROM**2) .", stats.accessible_surface) << std::endl;
// hydrogenbond summary
- os << cif::format("{:5d}{:5.1f} TOTAL NUMBER OF HYDROGEN BONDS OF TYPE O(I)-->H-N(J) , SAME NUMBER PER 100 RESIDUES .", stats.count.H_bonds, (stats.count.H_bonds * 100.0 / stats.count.residues)) << std::endl;
+ os << std::format("{:5d}{:5.1f} TOTAL NUMBER OF HYDROGEN BONDS OF TYPE O(I)-->H-N(J) , SAME NUMBER PER 100 RESIDUES .", stats.count.H_bonds, (stats.count.H_bonds * 100.0 / stats.count.residues)) << std::endl;
- os << cif::format("{:5d}{:5.1f} TOTAL NUMBER OF HYDROGEN BONDS IN PARALLEL BRIDGES, SAME NUMBER PER 100 RESIDUES .", stats.count.H_bonds_in_parallel_bridges, (stats.count.H_bonds_in_parallel_bridges * 100.0 / stats.count.residues)) << std::endl;
+ os << std::format("{:5d}{:5.1f} TOTAL NUMBER OF HYDROGEN BONDS IN PARALLEL BRIDGES, SAME NUMBER PER 100 RESIDUES .", stats.count.H_bonds_in_parallel_bridges, (stats.count.H_bonds_in_parallel_bridges * 100.0 / stats.count.residues)) << std::endl;
- os << cif::format("{:5d}{:5.1f} TOTAL NUMBER OF HYDROGEN BONDS IN ANTIPARALLEL BRIDGES, SAME NUMBER PER 100 RESIDUES .", stats.count.H_bonds_in_antiparallel_bridges, (stats.count.H_bonds_in_antiparallel_bridges * 100.0 / stats.count.residues)) << std::endl;
+ os << std::format("{:5d}{:5.1f} TOTAL NUMBER OF HYDROGEN BONDS IN ANTIPARALLEL BRIDGES, SAME NUMBER PER 100 RESIDUES .", stats.count.H_bonds_in_antiparallel_bridges, (stats.count.H_bonds_in_antiparallel_bridges * 100.0 / stats.count.residues)) << std::endl;
for (int k = 0; k < 11; ++k)
- os << cif::format("{:5d}{:5.1f} TOTAL NUMBER OF HYDROGEN BONDS OF TYPE O(I)-->H-N(I{:1c}{:1d}), SAME NUMBER PER 100 RESIDUES .", stats.count.H_Bonds_per_distance[k], (stats.count.H_Bonds_per_distance[k] * 100.0 / stats.count.residues), (k - 5 < 0 ? '-' : '+'), abs(k - 5)) << std::endl;
+ os << std::format("{:5d}{:5.1f} TOTAL NUMBER OF HYDROGEN BONDS OF TYPE O(I)-->H-N(I{:1c}{:1d}), SAME NUMBER PER 100 RESIDUES .", stats.count.H_Bonds_per_distance[k], (stats.count.H_Bonds_per_distance[k] * 100.0 / stats.count.residues), (k - 5 < 0 ? '-' : '+'), abs(k - 5)) << std::endl;
// histograms...
os << " 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 *** HISTOGRAMS OF *** ." << std::endl;
for (auto hi : stats.histogram.residues_per_alpha_helix)
- os << cif::format("{:3d}", hi);
+ os << std::format("{:3d}", hi);
os << " RESIDUES PER ALPHA HELIX ." << std::endl;
for (auto hi : stats.histogram.parallel_bridges_per_ladder)
- os << cif::format("{:3d}", hi);
+ os << std::format("{:3d}", hi);
os << " PARALLEL BRIDGES PER LADDER ." << std::endl;
for (auto hi : stats.histogram.antiparallel_bridges_per_ladder)
- os << cif::format("{:3d}", hi);
+ os << std::format("{:3d}", hi);
os << " ANTIPARALLEL BRIDGES PER LADDER ." << std::endl;
for (auto hi : stats.histogram.ladders_per_sheet)
- os << cif::format("{:3d}", hi);
+ os << std::format("{:3d}", hi);
os << " LADDERS PER SHEET ." << std::endl;
// per residue information
@@ -214,7 +218,7 @@ void writeDSSP(const dssp &dssp, std::ostream &os)
// can be the transition to a different chain, or missing residues in the current chain
if (ri.nr() != last + 1)
- os << cif::format("{:5d} !{:1c} 0 0 0 0, 0.0 0, 0.0 0, 0.0 0, 0.0 0.000 360.0 360.0 360.0 360.0 0.0 0.0 0.0",
+ os << std::format("{:5d} !{:1c} 0 0 0 0, 0.0 0, 0.0 0, 0.0 0, 0.0 0.000 360.0 360.0 360.0 360.0 0.0 0.0 0.0",
(last + 1), (ri.chain_break() == dssp::chain_break_type::NewChain ? '*' : ' '))
<< std::endl;
@@ -274,7 +278,7 @@ void writeBridgePairs(cif::datablock &db, const dssp &dssp)
data.emplace_back("acceptor_1_auth_seq_id", acceptor.auth_seq_id());
data.emplace_back("acceptor_1_auth_asym_id", acceptor.auth_asym_id());
data.emplace_back("acceptor_1_pdbx_PDB_ins_code", acceptor.pdb_ins_code());
- data.emplace_back("acceptor_1_energy", acceptorEnergy, 1);
+ data.emplace_back("acceptor_1_energy", { acceptorEnergy, 1 });
}
else
{
@@ -285,7 +289,7 @@ void writeBridgePairs(cif::datablock &db, const dssp &dssp)
data.emplace_back("acceptor_2_auth_seq_id", acceptor.auth_seq_id());
data.emplace_back("acceptor_2_auth_asym_id", acceptor.auth_asym_id());
data.emplace_back("acceptor_2_pdbx_PDB_ins_code", acceptor.pdb_ins_code());
- data.emplace_back("acceptor_2_energy", acceptorEnergy, 1);
+ data.emplace_back("acceptor_2_energy", { acceptorEnergy, 1 });
}
}
@@ -300,7 +304,7 @@ void writeBridgePairs(cif::datablock &db, const dssp &dssp)
data.emplace_back("donor_1_auth_seq_id", donor.auth_seq_id());
data.emplace_back("donor_1_auth_asym_id", donor.auth_asym_id());
data.emplace_back("donor_1_pdbx_PDB_ins_code", donor.pdb_ins_code());
- data.emplace_back("donor_1_energy", donorEnergy, 1);
+ data.emplace_back("donor_1_energy", { donorEnergy, 1 });
}
else
{
@@ -311,7 +315,7 @@ void writeBridgePairs(cif::datablock &db, const dssp &dssp)
data.emplace_back("donor_2_auth_seq_id", donor.auth_seq_id());
data.emplace_back("donor_2_auth_asym_id", donor.auth_asym_id());
data.emplace_back("donor_2_pdbx_PDB_ins_code", donor.pdb_ins_code());
- data.emplace_back("donor_2_energy", donorEnergy, 1);
+ data.emplace_back("donor_2_energy", { donorEnergy, 1 });
}
}
}
@@ -329,9 +333,8 @@ void writeSheets(cif::datablock &db, const dssp &dssp)
// clean up old info first
for (auto sheet_cat : { "struct_sheet", "struct_sheet_order", "struct_sheet_range", "struct_sheet_hbond", "pdbx_struct_sheet_hbond" })
- db.erase(remove_if(db.begin(), db.end(), [sheet_cat](const cif::category &cat)
- { return cat.name() == sheet_cat; }),
- db.end());
+ std::erase_if(db, [sheet_cat](const cif::category &cat)
+ { return cat.name() == sheet_cat; });
// create a list of strands, based on the SS info in DSSP. Store sheet number along with the strand.
@@ -370,7 +373,7 @@ void writeSheets(cif::datablock &db, const dssp &dssp)
std::string strandID = cif::cif_id_for_number(strand.front().strand() - 1);
- std::sort(strand.begin(), strand.end(), [](dssp::residue_info const &a, dssp::residue_info const &b)
+ std::ranges::sort(strand, [](dssp::residue_info const &a, dssp::residue_info const &b)
{ return a.nr() < b.nr(); });
auto &beg = strand.front();
@@ -388,10 +391,10 @@ void writeSheets(cif::datablock &db, const dssp &dssp)
{ "pdbx_end_PDB_ins_code", end.pdb_ins_code() },
{ "beg_auth_comp_id", beg.compound_id() },
{ "beg_auth_asym_id", beg.auth_asym_id() },
- { "beg_auth_seq_id", beg.auth_seq_id() },
+ { "beg_auth_seq_id", std::to_string(beg.auth_seq_id()) },
{ "end_auth_comp_id", end.compound_id() },
{ "end_auth_asym_id", end.auth_asym_id() },
- { "end_auth_seq_id", end.auth_seq_id() } });
+ { "end_auth_seq_id", std::to_string(end.auth_seq_id()) } });
}
}
}
@@ -439,7 +442,7 @@ void writeLadders(cif::datablock &db, const dssp &dssp)
assert(l.parallel == parallel);
- if (find_if(l.pairs.begin(), l.pairs.end(), [na = p.nr(), nb = res.nr()](const auto &p)
+ if (std::ranges::find_if(l.pairs, [na = p.nr(), nb = res.nr()](const auto &p)
{ return p.first.nr() == na and p.second.nr() == nb; }) != l.pairs.end())
{
is_new = false;
@@ -458,7 +461,7 @@ void writeLadders(cif::datablock &db, const dssp &dssp)
}
}
- std::sort(ladders.begin(), ladders.end());
+ std::ranges::sort(ladders, std::less<>());
auto &dssp_struct_ladder = db["dssp_struct_ladder"];
@@ -517,37 +520,36 @@ void writeStatistics(cif::datablock &db, const dssp &dssp)
if (stats.accessible_surface > 0)
surface_accessibility = stats.accessible_surface;
- auto stats_i = dssp_statistics.emplace({ //
- { "entry_id", db.name() },
+ auto stats_i = dssp_statistics.emplace({ { "entry_id", db.name() },
{ "nr_of_residues", stats.count.residues },
{ "nr_of_chains", stats.count.chains },
{ "nr_of_ss_bridges_total", stats.count.SS_bridges },
{ "nr_of_ss_bridges_intra_chain", stats.count.intra_chain_SS_bridges },
{ "nr_of_ss_bridges_inter_chain", stats.count.SS_bridges - stats.count.intra_chain_SS_bridges },
- { "accessible_surface_of_protein", surface_accessibility, 2 } });
+ { "accessible_surface_of_protein", { surface_accessibility, 2 } } });
auto &dssp_struct_hbonds = db["dssp_statistics_hbond"];
dssp_struct_hbonds.emplace({ { "entry_id", db.name() },
{ "type", "O(I)-->H-N(J)" },
{ "count", stats.count.H_bonds },
- { "count_per_100", stats.count.H_bonds * 100.0 / stats.count.residues, 1 } });
+ { "count_per_100", { stats.count.H_bonds * 100.0 / stats.count.residues, 1 } } });
dssp_struct_hbonds.emplace({ { "entry_id", db.name() },
{ "type", "PARALLEL BRIDGES" },
{ "count", stats.count.H_bonds_in_parallel_bridges },
- { "count_per_100", stats.count.H_bonds_in_parallel_bridges * 100.0 / stats.count.residues, 1 } });
+ { "count_per_100", { stats.count.H_bonds_in_parallel_bridges * 100.0 / stats.count.residues, 1 } } });
dssp_struct_hbonds.emplace({ { "entry_id", db.name() },
{ "type", "ANTIPARALLEL BRIDGES" },
{ "count", stats.count.H_bonds_in_antiparallel_bridges },
- { "count_per_100", stats.count.H_bonds_in_antiparallel_bridges * 100.0 / stats.count.residues, 1 } });
+ { "count_per_100", { stats.count.H_bonds_in_antiparallel_bridges * 100.0 / stats.count.residues, 1 } } });
for (int k = 0; k < 11; ++k)
dssp_struct_hbonds.emplace({ { "entry_id", db.name() },
- { "type", "O(I)-->H-N(I"s + char(k - 5 < 0 ? '-' : '+') + std::to_string(abs(k - 5)) + ")" },
+ { "type", "O(I)-->H-N(I"s + (k - 5 < 0 ? '-' : '+') + std::to_string(abs(k - 5)) + ")" },
{ "count", stats.count.H_Bonds_per_distance[k] },
- { "count_per_100", stats.count.H_Bonds_per_distance[k] * 100.0 / stats.count.residues, 1 } });
+ { "count_per_100", { stats.count.H_Bonds_per_distance[k] * 100.0 / stats.count.residues, 1 } } });
auto &dssp_statistics_histogram = db["dssp_statistics_histogram"];
@@ -700,43 +702,54 @@ void writeSummary(cif::datablock &db, const dssp &dssp)
{ "ladder_1", ladders[0] },
{ "ladder_2", ladders[1] },
- { "x_ca", cax, 1 },
- { "y_ca", cay, 1 },
- { "z_ca", caz, 1 },
+ { "x_ca", { cax, 1 } },
+ { "y_ca", { cay, 1 } },
+ { "z_ca", { caz, 1 } },
};
if (writeAccessibility)
- data.emplace_back("accessibility", res.accessibility(), 1);
+ data.emplace_back("accessibility", { res.accessibility(), 1 });
if (res.tco().has_value())
- data.emplace_back("TCO", *res.tco(), 3);
+ data.emplace_back("TCO", { *res.tco(), 3 });
else
- data.emplace_back("TCO", ".");
+ data.set_value("TCO", cif::item_value_type::INAPPLICABLE);
if (res.kappa().has_value())
- data.emplace_back("kappa", *res.kappa(), 1);
+ data.emplace_back("kappa", { *res.kappa(), 1 });
else
- data.emplace_back("kappa", ".");
+ data.set_value("kappa", cif::item_value_type::INAPPLICABLE);
if (res.alpha().has_value())
- data.emplace_back("alpha", *res.alpha(), 1);
+ data.emplace_back("alpha", { *res.alpha(), 1 });
else
- data.emplace_back("alpha", ".");
+ data.set_value("alpha", cif::item_value_type::INAPPLICABLE);
if (res.phi().has_value())
- data.emplace_back("phi", *res.phi(), 1);
+ data.emplace_back("phi", { *res.phi(), 1 });
else
- data.emplace_back("phi", ".");
+ data.set_value("phi", cif::item_value_type::INAPPLICABLE);
if (res.psi().has_value())
- data.emplace_back("psi", *res.psi(), 1);
+ data.emplace_back("psi", { *res.psi(), 1 });
else
- data.emplace_back("psi", ".");
+ data.set_value("psi", cif::item_value_type::INAPPLICABLE);
dssp_struct_summary.emplace(std::move(data));
}
}
+// Work around stupid change in signature of cif::validator_factory::get...
+template <typename ValidatorFactory>
+void fill_audit_conform(cif::category &audit_conform)
+{
+ auto &cf = ValidatorFactory::instance();
+ if constexpr (std::is_pointer_v<decltype(std::declval<cif::validator_factory>().get(""))>)
+ cf.get("mmcif_pdbx.dic")->fill_audit_conform(audit_conform);
+ else
+ cf.get("mmcif_pdbx.dic").fill_audit_conform(audit_conform);
+}
+
void annotateDSSP(cif::datablock &db, const dssp &dssp, bool writeOther, bool writeNewFormat)
{
using namespace std::literals;
@@ -744,10 +757,7 @@ void annotateDSSP(cif::datablock &db, const dssp &dssp, bool writeOther, bool wr
auto &audit_conform = db["audit_conform"];
if (audit_conform.empty())
- {
- auto &cf = cif::validator_factory::instance();
- cf.get("mmcif_pdbx.dic").fill_audit_conform(audit_conform);
- }
+ fill_audit_conform<cif::validator_factory>(audit_conform);
audit_conform.erase(cif::key("dict_name") == "dssp-extension.dic");
audit_conform.emplace({ //
@@ -771,10 +781,10 @@ void annotateDSSP(cif::datablock &db, const dssp &dssp, bool writeOther, bool wr
"dssp_statistics",
"dssp_statistics_hbond",
"dssp_statistics_histogram",
- "dssp_struct_summary"
- })
+ "dssp_struct_summary" })
{
- db.erase(std::remove_if(db.begin(), db.end(), [cat] (cif::category &c) { return c.name() == cat; }), db.end());
+ std::erase_if(db, [cat](cif::category &c)
+ { return c.name() == cat; });
}
if (writeNewFormat)
@@ -868,10 +878,10 @@ void annotateDSSP(cif::datablock &db, const dssp &dssp, bool writeOther, bool wr
{ "beg_auth_comp_id", rb.compound_id() },
{ "beg_auth_asym_id", rb.auth_asym_id() },
- { "beg_auth_seq_id", rb.auth_seq_id() },
+ { "beg_auth_seq_id", std::to_string(rb.auth_seq_id()) },
{ "end_auth_comp_id", re.compound_id() },
{ "end_auth_asym_id", re.auth_asym_id() },
- { "end_auth_seq_id", re.auth_seq_id() } });
+ { "end_auth_seq_id", std::to_string(re.auth_seq_id()) } });
st = t;
}
=====================================
libdssp/src/dssp.cpp
=====================================
@@ -30,8 +30,11 @@
#include "dssp-io.hpp"
+#include <algorithm>
#include <deque>
#include <iomanip>
+#include <memory>
+#include <numbers>
#include <numeric>
#include <thread>
@@ -49,7 +52,7 @@ using chain_break_type = dssp::chain_break_type;
// --------------------------------------------------------------------
const double
- kPI = 3.141592653589793238462643383279502884;
+ kPI = std::numbers::pi;
struct point
{
@@ -263,7 +266,6 @@ struct dssp::residue
: mPDBStrandID(pdb_strand_id)
, mPDBSeqNum(pdb_seq_num)
, mPDBInsCode(pdb_ins_code)
- , mChainBreak(chain_break_type::None)
, m_model_nr(model_nr)
{
// update the box containing all atoms
@@ -276,7 +278,7 @@ struct dssp::residue
p = {};
}
- void addAtom(cif::row_handle atom)
+ void addAtom(cif::const_row_handle atom)
{
std::string asymID, compID, atomID, type, authAsymID;
std::optional<std::string> altID;
@@ -393,7 +395,7 @@ struct dssp::residue
auto pc = mPrev->mC;
auto po = mPrev->mO;
- float CODistance = static_cast<float>(distance(pc, po));
+ auto CODistance = static_cast<float>(distance(pc, po));
mH.mX += (pc.mX - po.mX) / CODistance;
mH.mY += (pc.mY - po.mY) / CODistance;
@@ -402,7 +404,7 @@ struct dssp::residue
}
void SetSecondaryStructure(structure_type inSS) { mSecondaryStructure = inSS; }
- structure_type GetSecondaryStructure() const { return mSecondaryStructure; }
+ [[nodiscard]] structure_type GetSecondaryStructure() const { return mSecondaryStructure; }
void SetBetaPartner(uint32_t n, residue &inResidue, uint32_t inLadder, bool inParallel)
{
@@ -413,38 +415,38 @@ struct dssp::residue
mBetaPartner[n].parallel = inParallel;
}
- bridge_partner GetBetaPartner(uint32_t n) const
+ [[nodiscard]] bridge_partner GetBetaPartner(uint32_t n) const
{
assert(n == 0 or n == 1);
return mBetaPartner[n];
}
void SetSheet(uint32_t inSheet) { mSheet = inSheet; }
- uint32_t GetSheet() const { return mSheet; }
+ [[nodiscard]] uint32_t GetSheet() const { return mSheet; }
void SetStrand(uint32_t inStrand) { mStrand = inStrand; }
- uint32_t GetStrand() const { return mStrand; }
+ [[nodiscard]] uint32_t GetStrand() const { return mStrand; }
- bool IsBend() const { return mBend; }
+ [[nodiscard]] bool IsBend() const { return mBend; }
void SetBend(bool inBend) { mBend = inBend; }
- helix_position_type GetHelixFlag(helix_type helixType) const
+ [[nodiscard]] helix_position_type GetHelixFlag(helix_type helixType) const
{
- size_t stride = static_cast<size_t>(helixType);
+ auto stride = static_cast<size_t>(helixType);
assert(stride < 4);
return mHelixFlags[stride];
}
- bool IsHelixStart(helix_type helixType) const
+ [[nodiscard]] bool IsHelixStart(helix_type helixType) const
{
- size_t stride = static_cast<size_t>(helixType);
+ auto stride = static_cast<size_t>(helixType);
assert(stride < 4);
return mHelixFlags[stride] == helix_position_type::Start or mHelixFlags[stride] == helix_position_type::StartAndEnd;
}
void SetHelixFlag(helix_type helixType, helix_position_type inHelixFlag)
{
- size_t stride = static_cast<size_t>(helixType);
+ auto stride = static_cast<size_t>(helixType);
assert(stride < 4);
mHelixFlags[stride] = inHelixFlag;
}
@@ -456,7 +458,7 @@ struct dssp::residue
mSSBridgeNr = inBridgeNr;
}
- uint8_t GetSSBridgeNr() const
+ [[nodiscard]] uint8_t GetSSBridgeNr() const
{
if (mType != kCysteine)
throw std::runtime_error("Only cysteine residues can form sulphur bridges");
@@ -466,7 +468,7 @@ struct dssp::residue
float CalculateSurface(const std::vector<residue> &inResidues);
float CalculateSurface(const point &inAtom, float inRadius, const std::vector<residue *> &inNeighbours);
- bool AtomIntersectsBox(const point &atom, float inRadius) const
+ [[nodiscard]] bool AtomIntersectsBox(const point &atom, float inRadius) const
{
return atom.mX + inRadius >= mBox[0].mX and
atom.mX - inRadius <= mBox[1].mX and
@@ -572,9 +574,9 @@ class accumulator
double radius;
double distance;
- bool operator<(const candidate &rhs) const
+ auto operator<=>(const candidate &rhs) const
{
- return distance < rhs.distance;
+ return distance <=> rhs.distance;
}
};
@@ -593,13 +595,13 @@ class accumulator
candidate c = { b - a, r * r, distance };
m_x.push_back(c);
- push_heap(m_x.begin(), m_x.end());
+ std::ranges::push_heap(m_x, std::less<>());
}
}
void sort()
{
- sort_heap(m_x.begin(), m_x.end());
+ std::ranges::sort_heap(m_x, std::less<>());
}
std::vector<candidate> m_x;
@@ -611,9 +613,9 @@ class MSurfaceDots
public:
static MSurfaceDots &Instance();
- size_t size() const { return mPoints.size(); }
+ [[nodiscard]] size_t size() const { return mPoints.size(); }
const point &operator[](size_t inIx) const { return mPoints[inIx]; }
- double weight() const { return mWeight; }
+ [[nodiscard]] double weight() const { return mWeight; }
private:
MSurfaceDots(int32_t inN);
@@ -634,14 +636,14 @@ MSurfaceDots::MSurfaceDots(int32_t N)
{
auto P = 2 * N + 1;
- const float kGoldenRatio = (1 + std::sqrt(5.0f)) / 2;
+ const float kGoldenRatio = std::numbers::phi_v<float>;
mWeight = (4 * kPI) / P;
for (auto i = -N; i <= N; ++i)
{
float lat = std::asin((2.0f * i) / P);
- float lon = static_cast<float>(std::fmod(i, kGoldenRatio) * 2 * kPI / kGoldenRatio);
+ auto lon = static_cast<float>(std::fmod(i, kGoldenRatio) * 2 * kPI / kGoldenRatio);
mPoints.emplace_back(point{ std::sin(lon) * std::cos(lat), std::cos(lon) * std::cos(lat), std::sin(lat) });
}
@@ -778,8 +780,8 @@ double CalculateHBondEnergy(residue &inDonor, residue &inAcceptor)
void CalculateHBondEnergies(std::vector<residue> &inResidues, std::vector<std::tuple<uint32_t, uint32_t>> &q)
{
std::unique_ptr<cif::progress_bar> progress;
- if (cif::VERBOSE == 0 or cif::VERBOSE == 1)
- progress.reset(new cif::progress_bar(q.size(), "calculate hbond energies"));
+ if (cif::VERBOSE >= 0)
+ progress = std::make_unique<cif::progress_bar>(q.size(), "calculate hbond energies");
for (const auto &[i, j] : q)
{
@@ -873,8 +875,8 @@ void CalculateBetaSheets(std::vector<residue> &inResidues, statistics &stats, st
// std::cerr << "calculating beta sheets" << std::endl;
std::unique_ptr<cif::progress_bar> progress;
- if (cif::VERBOSE == 0 or cif::VERBOSE == 1)
- progress.reset(new cif::progress_bar(q.size(), "calculate beta sheets"));
+ if (cif::VERBOSE >= 0)
+ progress = std::make_unique<cif::progress_bar>(q.size(), "calculate beta sheets");
// Calculate Bridges
std::vector<bridge> bridges;
@@ -929,7 +931,7 @@ void CalculateBetaSheets(std::vector<residue> &inResidues, statistics &stats, st
}
// extend ladders
- std::sort(bridges.begin(), bridges.end());
+ std::ranges::sort(bridges, std::less<>());
for (uint32_t i = 0; i < bridges.size(); ++i)
{
@@ -1069,7 +1071,7 @@ void CalculateBetaSheets(std::vector<residue> &inResidues, statistics &stats, st
{
stats.count.H_bonds_in_parallel_bridges += bridge.i.back() - bridge.i.front() + 2;
- std::deque<uint32_t>::iterator j = bridge.j.begin();
+ auto j = bridge.j.begin();
for (uint32_t i : bridge.i)
inResidues[i].SetBetaPartner(betai, inResidues[*j++], bridge.ladder, true);
@@ -1081,7 +1083,7 @@ void CalculateBetaSheets(std::vector<residue> &inResidues, statistics &stats, st
{
stats.count.H_bonds_in_antiparallel_bridges += bridge.i.back() - bridge.i.front() + 2;
- std::deque<uint32_t>::reverse_iterator j = bridge.j.rbegin();
+ auto j = bridge.j.rbegin();
for (uint32_t i : bridge.i)
inResidues[i].SetBetaPartner(betai, inResidues[*j++], bridge.ladder, false);
@@ -1390,7 +1392,7 @@ struct DSSP_impl
auto findRes(const std::string &asymID, int seqID)
{
- return std::find_if(mResidues.begin(), mResidues.end(), [&](auto &r)
+ return std::ranges::find_if(mResidues, [&](auto &r)
{ return r.mAsymID == asymID and r.mSeqID == seqID; });
}
@@ -1454,9 +1456,8 @@ DSSP_impl::DSSP_impl(const cif::datablock &db, int model_nr, int min_poly_prolin
for (auto &residue : mResidues)
residue.finish();
- mResidues.erase(std::remove_if(mResidues.begin(), mResidues.end(), [](const dssp::residue &r)
- { return not r.mComplete; }),
- mResidues.end());
+ std::erase_if(mResidues, [](const dssp::residue &r)
+ { return not r.mComplete; });
mStats.count.chains = 1;
chain_break_type brk = chain_break_type::NewChain;
@@ -1592,8 +1593,8 @@ void DSSP_impl::calculateSecondaryStructure()
cAlphas.emplace_back(r.mCAlpha);
std::unique_ptr<cif::progress_bar> progress;
- if (cif::VERBOSE == 0 or cif::VERBOSE == 1)
- progress.reset(new cif::progress_bar((mResidues.size() * (mResidues.size() - 1)) / 2, "calculate distances"));
+ if (cif::VERBOSE >= 0)
+ progress = std::make_unique<cif::progress_bar>((mResidues.size() * (mResidues.size() - 1)) / 2, "calculate distances");
// Calculate the HBond energies
std::vector<std::tuple<uint32_t, uint32_t>> near;
@@ -1646,7 +1647,7 @@ void DSSP_impl::calculateSecondaryStructure()
auto id = r.mAsymID + ':' + std::to_string(r.mSeqID) + '/' + r.mCompoundID;
std::cerr << id << std::string(12 - id.length(), ' ')
- << char(r.mSecondaryStructure) << ' '
+ << static_cast<char>(r.mSecondaryStructure) << ' '
<< helix
<< std::endl;
}
@@ -1751,14 +1752,14 @@ std::string DSSP_impl::GetPDBHEADERLine()
for (auto r : cat1)
{
- keywords = FixStringLength(r["pdbx_keywords"].as<std::string>(), 40);
+ keywords = FixStringLength(r["pdbx_keywords"].get<std::string>(), 40);
break;
}
std::string date;
for (auto r : mDB["pdbx_database_status"])
{
- date = r["recvd_initial_deposition_date"].as<std::string>();
+ date = r["recvd_initial_deposition_date"].get<std::string>();
if (date.empty())
continue;
date = cif2pdbDate(date);
@@ -1769,7 +1770,7 @@ std::string DSSP_impl::GetPDBHEADERLine()
{
for (auto r : mDB["database_PDB_rev"])
{
- date = r["date_original"].as<std::string>();
+ date = r["date_original"].get<std::string>();
if (date.empty())
continue;
date = cif2pdbDate(date);
@@ -1784,8 +1785,8 @@ std::string DSSP_impl::GetPDBHEADERLine()
char header[] =
"HEADER xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxDDDDDDDDD IIII";
- std::copy(keywords.begin(), keywords.end(), header + 10);
- std::copy(date.begin(), date.end(), header + 50);
+ std::ranges::copy(keywords, header + 10);
+ std::ranges::copy(date, header + 50);
std::string id = mDB.name();
if (id.length() < 4)
@@ -1793,7 +1794,7 @@ std::string DSSP_impl::GetPDBHEADERLine()
else if (id.length() > 4)
id.erase(id.begin() + 4, id.end());
- std::copy(id.begin(), id.end(), header + 62);
+ std::ranges::copy(id, header + 62);
return FixStringLength(header);
}
@@ -1809,45 +1810,45 @@ std::string DSSP_impl::GetPDBCOMPNDLine()
for (auto r : mDB["entity"].find("type"_key == "polymer"))
{
- std::string entityID = r["id"].as<std::string>();
+ auto entityID = r["id"].get<std::string>();
++molID;
cmpnd.push_back("MOL_ID: " + std::to_string(molID));
- std::string molecule = r["pdbx_description"].as<std::string>();
+ auto molecule = r["pdbx_description"].get<std::string>();
cmpnd.push_back("MOLECULE: " + molecule);
auto poly = mDB["entity_poly"].find("entity_id"_key == entityID);
if (not poly.empty())
{
- std::string chains = poly.front()["pdbx_strand_id"].as<std::string>();
+ auto chains = poly.front()["pdbx_strand_id"].get<std::string>();
cif::replace_all(chains, ",", ", ");
cmpnd.push_back("CHAIN: " + chains);
}
- std::string fragment = r["pdbx_fragment"].as<std::string>();
+ auto fragment = r["pdbx_fragment"].get<std::string>();
if (not fragment.empty())
cmpnd.push_back("FRAGMENT: " + fragment);
for (auto sr : mDB["entity_name_com"].find("entity_id"_key == entityID))
{
- std::string syn = sr["name"].as<std::string>();
+ auto syn = sr["name"].get<std::string>();
if (not syn.empty())
cmpnd.push_back("SYNONYM: " + syn);
}
- std::string mutation = r["pdbx_mutation"].as<std::string>();
+ auto mutation = r["pdbx_mutation"].get<std::string>();
if (not mutation.empty())
cmpnd.push_back("MUTATION: " + mutation);
- std::string ec = r["pdbx_ec"].as<std::string>();
+ auto ec = r["pdbx_ec"].get<std::string>();
if (not ec.empty())
cmpnd.push_back("EC: " + ec);
if (r["src_method"] == "man" or r["src_method"] == "syn")
- cmpnd.push_back("ENGINEERED: YES");
+ cmpnd.emplace_back("ENGINEERED: YES");
- std::string details = r["details"].as<std::string>();
+ auto details = r["details"].get<std::string>();
if (not details.empty())
cmpnd.push_back("OTHER_DETAILS: " + details);
}
@@ -1869,13 +1870,13 @@ std::string DSSP_impl::GetPDBSOURCELine()
if (r["type"] != "polymer")
continue;
- std::string entityID = r["id"].as<std::string>();
+ auto entityID = r["id"].get<std::string>();
++molID;
source.push_back("MOL_ID: " + std::to_string(molID));
if (r["src_method"] == "syn")
- source.push_back("SYNTHETIC: YES");
+ source.emplace_back("SYNTHETIC: YES");
auto &gen = mDB["entity_src_gen"];
const std::pair<const char *, const char *> kGenSourceMapping[] = {
@@ -1905,7 +1906,7 @@ std::string DSSP_impl::GetPDBSOURCELine()
std::string cname, sname;
tie(cname, sname) = m;
- std::string s = gr[cname].as<std::string>();
+ auto s = gr[cname].get<std::string>();
if (not s.empty())
source.push_back(sname + ": " + s);
}
@@ -1930,7 +1931,7 @@ std::string DSSP_impl::GetPDBSOURCELine()
std::string cname, sname;
tie(cname, sname) = m;
- std::string s = nr[cname].as<std::string>();
+ auto s = nr[cname].get<std::string>();
if (not s.empty())
source.push_back(sname + ": " + s);
}
@@ -1945,7 +1946,7 @@ std::string DSSP_impl::GetPDBAUTHORLine()
// AUTHOR
std::vector<std::string> author;
for (auto r : mDB["audit_author"])
- author.push_back(cif2pdbAuth(r["name"].as<std::string>()));
+ author.push_back(cif2pdbAuth(r["name"].get<std::string>()));
return FixStringLength("AUTHOR " + cif::join(author, "; "), kTruncateAt);
}
@@ -2186,7 +2187,7 @@ std::tuple<dssp::residue_info, double> dssp::residue_info::donor(int i) const
dssp::residue_info dssp::residue_info::next() const
{
- return residue_info(m_impl ? m_impl->mNext : nullptr);
+ return { m_impl ? m_impl->mNext : nullptr };
}
// --------------------------------------------------------------------
@@ -2220,7 +2221,8 @@ dssp::dssp(const cif::datablock &db, int model_nr, int min_poly_proline_stretch,
{
if (calculateSurfaceAccessibility)
{
- std::thread t(std::bind(&DSSP_impl::calculateSurface, m_impl));
+ std::thread t([this]
+ { m_impl->calculateSurface(); });
m_impl->calculateSecondaryStructure();
t.join();
}
@@ -2235,7 +2237,7 @@ dssp::~dssp()
dssp::iterator dssp::begin() const
{
- return iterator(m_impl->mResidues.empty() ? nullptr : m_impl->mResidues.data());
+ return { m_impl->mResidues.empty() ? nullptr : m_impl->mResidues.data() };
}
dssp::iterator dssp::end() const
@@ -2248,12 +2250,12 @@ dssp::iterator dssp::end() const
res += m_impl->mResidues.size();
}
- return iterator(res);
+ return { res };
}
dssp::residue_info dssp::operator[](const key_type &key) const
{
- auto i = std::find_if(begin(), end(),
+ auto i = std::ranges::find_if(*this,
[key](const residue_info &res)
{ return res.asym_id() == std::get<0>(key) and res.seq_id() == std::get<1>(key); });
=====================================
python-module/CMakeLists.txt
=====================================
@@ -25,55 +25,41 @@
include(CPM)
if(CMAKE_VERSION GREATER_EQUAL 3.30)
- cmake_policy(SET CMP0167 NEW)
+ cmake_policy(SET CMP0167 NEW)
endif()
-find_package(Python REQUIRED COMPONENTS Interpreter Development)
-find_package(Boost 1.83 QUIET COMPONENTS python)
+find_package(Python 3.13 REQUIRED COMPONENTS Interpreter Development)
-if(NOT Boost_FOUND)
- # boost is a huge project and directly downloading the 'alternate release'
- # from github is much faster than recursively cloning the repo.
- CPMAddPackage(
- NAME Boost
- VERSION 1.84.0
- URL https://github.com/boostorg/boost/releases/download/boost-1.84.0/boost-1.84.0.tar.xz
- URL_HASH SHA256=2e64e5d79a738d0fa6fb546c6e5c2bd28f88d268a2a080546f74e5ff98f29d0e
- OPTIONS
- "BOOST_ENABLE_CMAKE ON"
- "BOOST_INCLUDE_LIBRARIES python"
- "BOOST_ENABLE_PYTHON ON"
- "CMAKE_POSITION_INDEPENDENT_CODE ON"
- )
+if(NOT EXISTS ${Python_LIBRARIES})
+ message(FATAL_ERROR "The python library ${Python_LIBRARIES} does not seem to exist?")
endif()
+find_package(Boost 1.86 REQUIRED COMPONENTS python)
+
# ---------
add_library(mkdssp_module SHARED dssp-python-plugin.cpp)
target_compile_features(mkdssp_module PUBLIC cxx_std_20)
-
target_include_directories(mkdssp_module PRIVATE ${Python_INCLUDE_DIRS})
-target_link_libraries(mkdssp_module dssp::dssp Boost::python ${Python_LIBRARIES})
+target_link_libraries(mkdssp_module PRIVATE dssp::dssp ${Python_LIBRARIES} Boost::python)
set_target_properties(mkdssp_module
- PROPERTIES
- PREFIX ""
- SUFFIX ".so"
- OUTPUT_NAME mkdssp
- LINKER_LANGUAGE CXX
- LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib
-)
+ PROPERTIES
+ PREFIX ""
+ SUFFIX ".so"
+ OUTPUT_NAME mkdssp
+ LINKER_LANGUAGE CXX
+ LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
if(WIN32)
- # python modules use this on Windows
- set_target_properties(
- mkdssp_module
- PROPERTIES
- SUFFIX ".pyd"
- RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin
- )
+ # python modules use this on Windows
+ set_target_properties(
+ mkdssp_module
+ PROPERTIES
+ SUFFIX ".pyd"
+ RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
- install(TARGETS mkdssp_module RUNTIME DESTINATION "${Python_SITELIB}")
+ install(TARGETS mkdssp_module RUNTIME DESTINATION "${Python_SITELIB}")
else()
- install(TARGETS mkdssp_module LIBRARY DESTINATION "${Python_SITELIB}")
-endif()
\ No newline at end of file
+ install(TARGETS mkdssp_module LIBRARY DESTINATION "${Python_SITELIB}")
+endif()
=====================================
python-module/dssp-python-plugin.cpp
=====================================
@@ -2,6 +2,7 @@
#include <Python.h>
#include <dssp.hpp>
+#include <memory>
struct statistics_wrapper
{
@@ -42,7 +43,7 @@ class dssp_wrapper
std::istream is(&buffer);
auto f = cif::pdb::read(is);
- m_dssp.reset(new dssp(f.front(), model_nr, min_poly_proline_stretch_length, calculateSurfaceAccessibility));
+ m_dssp = std::make_shared<dssp>(f.front(), model_nr, min_poly_proline_stretch_length, calculateSurfaceAccessibility);
}
dssp_wrapper(const dssp_wrapper &) = default;
@@ -83,7 +84,7 @@ class dssp_wrapper
iterator(const iterator &i) = default;
iterator &operator=(const iterator &i) = default;
- reference operator*() { return residue_info_handle(m_current); }
+ reference operator*() { return {m_current}; }
pointer operator->() { return &m_current; }
iterator &operator++()
@@ -126,12 +127,12 @@ class dssp_wrapper
// Custom exceptions
struct AttributeError : std::exception
{
- const char *what() const throw() { return "AttributeError exception"; }
+ [[nodiscard]] const char *what() const noexcept override { return "AttributeError exception"; }
};
struct TypeError : std::exception
{
- const char *what() const throw() { return "TypeError exception"; }
+ [[nodiscard]] const char *what() const noexcept override { return "TypeError exception"; }
};
// Set python exceptions
=====================================
src/mkdssp.cpp
=====================================
@@ -33,7 +33,7 @@
#include <fstream>
#include <iostream>
-#include <cif++.hpp>
+#include <cif++/cif++.hpp>
#include <mcfp/mcfp.hpp>
#include "dssp.hpp"
=====================================
test/CMakeLists.txt
=====================================
@@ -1,32 +1,39 @@
CPMFindPackage(
- NAME Catch2 3
- GIT_REPOSITORY https://github.com/catchorg/Catch2.git
- GIT_TAG v3.4.0
- EXCLUDE_FROM_ALL YES)
+ NAME Catch2 3
+ GIT_REPOSITORY https://github.com/catchorg/Catch2.git
+ GIT_TAG v3.4.0
+ EXCLUDE_FROM_ALL YES)
add_executable(unit-test-dssp ${CMAKE_CURRENT_SOURCE_DIR}/unit-test-dssp.cpp ${PROJECT_SOURCE_DIR}/libdssp/src/dssp-io.cpp)
target_include_directories(unit-test-dssp PRIVATE
- ${CMAKE_CURRENT_SOURCE_DIR}/src
- ${CMAKE_CURRENT_SOURCE_DIR}/include
+ ${CMAKE_CURRENT_SOURCE_DIR}/src
+ ${CMAKE_CURRENT_SOURCE_DIR}/include
)
target_link_libraries(unit-test-dssp PRIVATE dssp cifpp::cifpp Catch2::Catch2)
if(MSVC)
- # Specify unwind semantics so that MSVC knowns how to handle exceptions
- target_compile_options(unit-test-dssp PRIVATE /EHsc)
+ # Specify unwind semantics so that MSVC knowns how to handle exceptions
+ target_compile_options(unit-test-dssp PRIVATE /EHsc)
endif()
add_test(NAME unit-test-dssp COMMAND $<TARGET_FILE:unit-test-dssp>
- --data-dir ${CMAKE_CURRENT_SOURCE_DIR}
- --rsrc-dir ${CMAKE_CURRENT_SOURCE_DIR}/../libdssp/mmcif_pdbx/)
+ --data-dir ${CMAKE_CURRENT_SOURCE_DIR}
+ --rsrc-dir ${CIFPP_DATA_DIR})
if(BUILD_PYTHON_MODULE)
- find_package(Python REQUIRED Interpreter)
+ find_package(Python REQUIRED Interpreter)
- add_test(NAME python_module COMMAND ${Python_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/test-python.py")
- set_tests_properties(python_module PROPERTIES
- ENVIRONMENT "PYTHONPATH=$<TARGET_FILE_DIR:mkdssp_module>"
- WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}")
-endif()
\ No newline at end of file
+ add_test(NAME python_module COMMAND ${Python_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/test-python.py")
+ set_tests_properties(python_module PROPERTIES
+ ENVIRONMENT
+ "PYTHONPATH=$<TARGET_FILE_DIR:mkdssp_module>;LIBCIFPP_DATA_DIR=${CIFPP_DATA_DIR}"
+ WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}")
+
+ add_test(NAME python_module_numpy COMMAND ${Python_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/test_numpy2_compat.py")
+ set_tests_properties(python_module_numpy PROPERTIES
+ ENVIRONMENT
+ "PYTHONPATH=$<TARGET_FILE_DIR:mkdssp_module>;LIBCIFPP_DATA_DIR=${CIFPP_DATA_DIR}"
+ WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}")
+endif()
=====================================
test/test_numpy2_compat.py
=====================================
@@ -0,0 +1,176 @@
+"""
+DSSP numpy 2.x compatibility test script
+This script tests whether the DSSP module works correctly with numpy 2.x
+"""
+
+import sys
+import os
+import gzip
+import traceback
+
+def find_test_file():
+ """Find the test CIF file in the repository"""
+ # Possible paths relative to script location
+ possible_paths = [
+ "test/1cbs.cif.gz", # From repository root
+ "../test/1cbs.cif.gz", # From python-module directory
+ "1cbs.cif.gz", # From test directory
+ ]
+
+ for path in possible_paths:
+ if os.path.exists(path):
+ return path
+
+ return None
+
+def test_numpy_version():
+ """Check numpy version"""
+ try:
+ import numpy as np
+ print(f"✓ numpy version: {np.__version__}")
+ major_version = int(np.__version__.split('.')[0])
+ if major_version >= 2:
+ print("✓ numpy 2.x detected")
+ else:
+ print(f"⚠ numpy {np.__version__} detected (not 2.x)")
+ return True
+ except ImportError as e:
+ print(f"✗ Failed to import numpy: {e}")
+ return False
+
+def test_mkdssp_import():
+ """Test mkdssp module import"""
+ try:
+ import mkdssp
+ print("✓ Successfully imported mkdssp module")
+ return True
+ except ImportError as e:
+ print(f"✗ Failed to import mkdssp: {e}")
+ traceback.print_exc()
+ return False
+
+def test_basic_functionality():
+ """Test basic functionality"""
+ try:
+ from mkdssp import dssp, TestBond, helix_type, chain_break_type, helix_position_type, structure_type
+ print("✓ Successfully imported all mkdssp classes/functions")
+
+ # Find test file
+ test_file = find_test_file()
+ if test_file is None:
+ print("✗ Could not find test file (1cbs.cif.gz)")
+ print(" Please run this script from the repository root or test directory")
+ return False
+
+ print(f"✓ Found test file: {test_file}")
+
+ # Read test file
+ try:
+ with gzip.open(test_file, "rt") as f:
+ file_content = f.read()
+ print("✓ Successfully read test file")
+ except Exception as e:
+ print(f"✗ Failed to read test file: {e}")
+ return False
+
+ # Test DSSP object creation
+ try:
+ dssp_obj = dssp(file_content)
+ print("✓ Successfully created DSSP object")
+ except Exception as e:
+ print(f"✗ Failed to create DSSP object: {e}")
+ traceback.print_exc()
+ return False
+
+ # Test statistics
+ try:
+ stats = dssp_obj.statistics
+ print(f"✓ Successfully retrieved statistics")
+ print(f" - Residues: {stats.residues}")
+ print(f" - Chains: {stats.chains}")
+ print(f" - H-bonds: {stats.H_bonds}")
+ except Exception as e:
+ print(f"✗ Failed to retrieve statistics: {e}")
+ traceback.print_exc()
+ return False
+
+ # Test iteration
+ try:
+ count = 0
+ for res in dssp_obj:
+ count += 1
+ if count == 1:
+ # Check first residue
+ print(f" - First residue: {res.asym_id} {res.seq_id} {res.compound_id}")
+ print(f"✓ Successfully iterated through {count} residues")
+ except Exception as e:
+ print(f"✗ Failed to iterate through residues: {e}")
+ traceback.print_exc()
+ return False
+
+ # Test TestBond function
+ try:
+ a = dssp_obj.get('A', 137)
+ b = dssp_obj.get('A', 6)
+ result = TestBond(a, b)
+ print(f"✓ Successfully tested TestBond function: {result}")
+ except Exception as e:
+ print(f"✗ Failed to test TestBond function: {e}")
+ traceback.print_exc()
+ return False
+
+ return True
+
+ except Exception as e:
+ print(f"✗ Basic functionality test failed: {e}")
+ traceback.print_exc()
+ return False
+
+def main():
+ """Main test function"""
+ print("=" * 60)
+ print("DSSP numpy 2.x Compatibility Test")
+ print("=" * 60)
+ print()
+
+ all_passed = True
+
+ # Test 1: Check numpy version
+ print("Test 1: Check numpy version")
+ if not test_numpy_version():
+ all_passed = False
+ print()
+
+ # Test 2: Import mkdssp
+ print("Test 2: Import mkdssp module")
+ if not test_mkdssp_import():
+ all_passed = False
+ print("\n⚠ Cannot import mkdssp, skipping remaining tests")
+ print_summary(False)
+ return 1
+ print()
+
+ # Test 3: Basic functionality
+ print("Test 3: Test basic functionality")
+ if not test_basic_functionality():
+ all_passed = False
+ print()
+
+ # Summary
+ print_summary(all_passed)
+
+ return 0 if all_passed else 1
+
+def print_summary(all_passed):
+ """Print test summary"""
+ print("=" * 60)
+ if all_passed:
+ print("✓ All tests passed!")
+ print("✓ DSSP appears to be compatible with numpy 2.x")
+ else:
+ print("✗ Some tests failed")
+ print("✗ There may be compatibility issues with numpy 2.x")
+ print("=" * 60)
+
+if __name__ == "__main__":
+ sys.exit(main())
=====================================
test/unit-test-dssp.cpp
=====================================
@@ -24,16 +24,13 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include <stdexcept>
-
#define CATCH_CONFIG_RUNNER
-#include <catch2/catch_all.hpp>
-
#include "../libdssp/src/dssp-io.hpp"
#include "../src/revision.hpp"
#include "dssp.hpp"
+#include <catch2/catch_all.hpp>
#include <cif++/dictionary_parser.hpp>
namespace fs = std::filesystem;
@@ -56,10 +53,12 @@ cif::file operator""_cf(const char *text, size_t length)
// --------------------------------------------------------------------
-std::filesystem::path gTestDir = std::filesystem::current_path();
+std::filesystem::path gTestDir;
int main(int argc, char *argv[])
{
+ gTestDir = std::filesystem::current_path();
+
Catch::Session session; // There must be exactly one instance
// Build a new parser on top of Catch2's
@@ -156,8 +155,6 @@ TEST_CASE("ut_mmcif_2")
dssp dssp(f.front(), 1, 3, true);
- std::stringstream test;
-
dssp.annotate(f.front(), true, true);
cif::file rf(gTestDir / "1cbs-dssp.cif");
@@ -166,12 +163,12 @@ TEST_CASE("ut_mmcif_2")
auto &db2 = rf.front();
db1["software"].erase("name"_key == "dssp");
- db1.erase(find_if(db1.begin(), db1.end(), [](cif::category &cat)
- { return cat.name() == "audit_conform"; }));
+ std::erase_if(db1, [](cif::category &cat)
+ { return cat.name() == "audit_conform"; });
db2["software"].erase("name"_key == "dssp");
- db2.erase(find_if(db2.begin(), db2.end(), [](cif::category &cat)
- { return cat.name() == "audit_conform"; }));
+ std::erase_if(db2, [](cif::category &cat)
+ { return cat.name() == "audit_conform"; });
// generate some output on different files:
// cif::VERBOSE = 2;
=====================================
tools/depends.cmd
=====================================
@@ -1,6 +1,5 @@
@ECHO OFF
SET ZLIB_VERSION=1.3
-SET PCRE2_VERSION=10.45
IF NOT EXIST build_ci\libs (
MKDIR build_ci\libs
@@ -22,19 +21,4 @@ cmake --build build --target ALL_BUILD --config Release || EXIT /b 1
cmake --build build --target RUN_TESTS --config Release || EXIT /b 1
cmake --build build --target INSTALL --config Release || EXIT /b 1
- at REM Install PCRE2
-IF NOT EXIST pcre2-%PCRE2_VERSION%.zip (
- ECHO Downloading https://github.com/PCRE2Project/pcre2/releases/download/pcre2-%PCRE2_VERSION%/pcre2-%PCRE2_VERSION%.zip
- curl -L -o pcre2-%PCRE2_VERSION%.zip https://github.com/PCRE2Project/pcre2/releases/download/pcre2-%PCRE2_VERSION%/pcre2-%PCRE2_VERSION%.zip || EXIT /b 1
-)
-IF NOT EXIST pcre2-%PCRE2_VERSION% (
- ECHO Unpacking pcre2-%PCRE2_VERSION%.zip
- C:\windows\system32\tar.exe -x -f pcre2-%PCRE2_VERSION%.zip || EXIT /b 1
-)
-CD pcre2-%PCRE2_VERSION%
-cmake -B build -DPCRE2_BUILD_PCRE2GREP=OFF || EXIT /b 1
-cmake --build build --target ALL_BUILD --config Release || EXIT /b 1
- at REM cmake --build build --target RUN_TESTS --config Release || EXIT /b 1
-cmake --build build --target INSTALL --config Release || EXIT /b 1
-
@EXIT /b 0
View it on GitLab: https://salsa.debian.org/med-team/dssp/-/commit/a41ec052abf2c8c326646b10b68a5231ce815173
--
View it on GitLab: https://salsa.debian.org/med-team/dssp/-/commit/a41ec052abf2c8c326646b10b68a5231ce815173
You're receiving this email because of your account on salsa.debian.org.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/debian-med-commit/attachments/20260324/8f7e7079/attachment-0001.htm>
More information about the debian-med-commit
mailing list