mirror of
https://github.com/PDB-REDO/dssp.git
synced 2026-06-04 13:44:21 +08:00
Require boost 1.84 or higher for numpy 2
Fix interface to be more compliant with standard concepts
This commit is contained in:
22
.clang-format
Normal file
22
.clang-format
Normal file
@@ -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
|
||||
18
.clang-tidy
Normal file
18
.clang-tidy
Normal file
@@ -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
|
||||
2
.github/workflows/cmake-multi-platform.yml
vendored
2
.github/workflows/cmake-multi-platform.yml
vendored
@@ -39,7 +39,7 @@ 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 libboost1.84-all-dev
|
||||
|
||||
- name: setup python
|
||||
uses: actions/setup-python@v5
|
||||
|
||||
@@ -32,6 +32,8 @@
|
||||
#include <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>);
|
||||
@@ -25,14 +25,13 @@
|
||||
*/
|
||||
|
||||
#include "dssp-io.hpp"
|
||||
|
||||
#include "revision.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cif++.hpp>
|
||||
#include <cif++/dictionary_parser.hpp>
|
||||
|
||||
#include <exception>
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include <format>
|
||||
#include <iostream>
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
@@ -121,20 +120,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 +166,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 +213,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;
|
||||
|
||||
@@ -329,9 +328,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 +368,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();
|
||||
@@ -458,7 +456,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"];
|
||||
|
||||
@@ -746,7 +744,7 @@ void annotateDSSP(cif::datablock &db, const dssp &dssp, bool writeOther, bool wr
|
||||
if (audit_conform.empty())
|
||||
{
|
||||
auto &cf = cif::validator_factory::instance();
|
||||
cf.get("mmcif_pdbx.dic").fill_audit_conform(audit_conform);
|
||||
cf.get("mmcif_pdbx.dic")->fill_audit_conform(audit_conform);
|
||||
}
|
||||
|
||||
audit_conform.erase(cif::key("dict_name") == "dssp-extension.dic");
|
||||
@@ -771,10 +769,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)
|
||||
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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"].as<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"].as<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"].as<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"].as<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"].as<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"].as<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"].as<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"].as<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"].as<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].as<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].as<std::string>();
|
||||
if (not s.empty())
|
||||
source.push_back(sname + ": " + s);
|
||||
}
|
||||
@@ -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); });
|
||||
|
||||
|
||||
@@ -29,7 +29,9 @@ if(CMAKE_VERSION GREATER_EQUAL 3.30)
|
||||
endif()
|
||||
|
||||
find_package(Python REQUIRED COMPONENTS Interpreter Development)
|
||||
find_package(Boost 1.83 QUIET COMPONENTS python)
|
||||
|
||||
# Boost 1.84 is required since it contains code required to use numpy 2.x
|
||||
find_package(Boost 1.84 QUIET COMPONENTS python)
|
||||
|
||||
if(NOT Boost_FOUND)
|
||||
# boost is a huge project and directly downloading the 'alternate release'
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user