Merge branch 'new-item-storage-plus' of github.com:PDB-REDO/libcifpp into new-item-storage-plus

This commit is contained in:
Maarten L. Hekkelman
2026-02-12 14:43:39 +01:00
8 changed files with 53 additions and 31 deletions

View File

@@ -153,9 +153,16 @@ class item_value
item_value(std::string_view s)
{
m_data.m_type = item_value_type::TEXT;
m_data.m_len = s.length();
m_data.m_value = s;
if (s == ".")
m_data.m_type = item_value_type::INAPPLICABLE;
else if (s == "?")
m_data.m_type = item_value_type::MISSING;
else
{
m_data.m_type = item_value_type::TEXT;
m_data.m_len = s.length();
m_data.m_value = s;
}
}
template <size_t N>
@@ -290,6 +297,8 @@ class item_value
template <IntegralType T>
[[nodiscard]] std::remove_cvref_t<T> get() const
{
static_assert(not std::is_same_v<std::remove_cvref_t<T>, bool>, "bool is no longer supported");
switch (m_data.m_type)
{
case item_value_type::INT:

View File

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

View File

@@ -174,9 +174,16 @@ compound::compound(cif::datablock &db)
{
compound_atom atom;
std::string type_symbol, stereo_config;
cif::tie(atom.id, type_symbol, atom.charge, atom.aromatic, atom.leaving_atom, stereo_config, atom.x, atom.y, atom.z) =
std::string aromaticFlag, leavingAtomFlag;
cif::tie(atom.id, type_symbol, atom.charge, aromaticFlag, leavingAtomFlag, stereo_config, atom.x, atom.y, atom.z) =
row.get("atom_id", "type_symbol", "charge", "pdbx_aromatic_flag", "pdbx_leaving_atom_flag", "pdbx_stereo_config",
"model_Cartn_x", "model_Cartn_y", "model_Cartn_z");
atom.aromatic = iequals(aromaticFlag, "Y");
atom.leaving_atom = iequals(leavingAtomFlag, "Y");
atom.type_symbol = atom_type_traits(type_symbol).type();
if (stereo_config.empty())
atom.stereo_config = stereo_config_type::N;
@@ -189,8 +196,13 @@ compound::compound(cif::datablock &db)
for (auto row : chemCompBond)
{
compound_bond bond;
std::string valueOrder;
cif::tie(bond.atom_id[0], bond.atom_id[1], valueOrder, bond.aromatic, bond.stereo_config) = row.get("atom_id_1", "atom_id_2", "value_order", "pdbx_aromatic_flag", "pdbx_stereo_config");
std::string valueOrder, aromaticFlag, stereoConfigFlag;
cif::tie(bond.atom_id[0], bond.atom_id[1], valueOrder, aromaticFlag, stereoConfigFlag) = row.get("atom_id_1", "atom_id_2", "value_order", "pdbx_aromatic_flag", "pdbx_stereo_config");
bond.aromatic = iequals(aromaticFlag, "Y");
bond.stereo_config = iequals(stereoConfigFlag, "Y");
if (valueOrder.empty())
bond.type = bond_type::sing;
else
@@ -576,7 +588,7 @@ compound *local_compound_factory_impl::construct_compound(const datablock &rdb,
}
for (std::size_t ord = 1; const auto &[atom_id_1, atom_id_2, type, aromatic] :
rdb["chem_comp_bond"].rows<std::string, std::string, std::string, bool>("atom_id_1", "atom_id_2", "type", "aromatic"))
rdb["chem_comp_bond"].rows<std::string, std::string, std::string, std::string>("atom_id_1", "atom_id_2", "type", "aromatic"))
{
std::string value_order("SING");

View File

@@ -232,7 +232,7 @@ atom residue::create_new_atom(atom_type inType, const std::string &inAtomID, poi
{ "label_entity_id", get_entity_id() },
{ "label_atom_id", inAtomID },
{ "label_asym_id", m_asym_id },
{ "label_alt_id", "." },
{ "label_alt_id", nullptr },
{ "label_comp_id", m_compound_id },
{ "label_seq_id", m_seq_id },
{ "auth_asym_id", m_pdb_strand_id },
@@ -952,8 +952,8 @@ cif::mm::atom sugar::add_atom(row_initializer atom_info)
atom_info.set_value({ "label_entity_id", m_branch->get_entity_id() });
atom_info.set_value({ "label_asym_id", m_branch->get_asym_id() });
atom_info.set_value({ "label_comp_id", m_compound_id });
atom_info.set_value({ "label_seq_id", "." });
atom_info.set_value({ "label_alt_id", "." });
atom_info.set_value({ "label_seq_id", nullptr });
atom_info.set_value({ "label_alt_id", nullptr });
atom_info.set_value({ "auth_asym_id", m_branch->get_asym_id() });
atom_info.set_value({ "auth_comp_id", m_compound_id });
atom_info.set_value({ "auth_seq_id", m_pdb_seq_num });
@@ -1107,7 +1107,7 @@ sugar &branch::construct_sugar(const std::string &compound_id, const std::string
{ "entity_branch_list_num_2", linked.num() },
{ "comp_id_2", linked.get_compound_id() },
{ "atom_id_2", linked_atom_id },
{ "leaving_atom_id_2", "." },
{ "leaving_atom_id_2", nullptr },
{ "value_order", "sing" } });
return result;
@@ -1165,7 +1165,7 @@ structure::structure(datablock &db, std::size_t modelNr, structure_open_options
load_atoms_for_model(options);
// Check to see if we should actually load another model?
if (m_atoms.empty() and m_model_nr == 1)
if (m_atoms.empty() and m_model_nr == 1 and not atom_site.empty())
{
auto model_nr =
atom_site.front().get<std::optional<std::size_t>>("pdbx_PDB_model_num");
@@ -1958,7 +1958,7 @@ void structure::change_residue(residue &res, const std::string &newCompound,
if (r.size() != 1)
continue;
if (a2.empty() or a2 == ".")
if (a2.empty())
{
i->set_property("label_comp_id", newCompound);
remove_atom(*i);
@@ -2208,7 +2208,7 @@ std::string structure::create_non_poly(const std::string &entity_id, const std::
{ "label_comp_id", comp_id },
{ "label_asym_id", asym_id },
{ "label_entity_id", entity_id },
{ "label_seq_id", "." },
{ "label_seq_id", nullptr },
{ "pdbx_PDB_ins_code", "" },
{ "Cartn_x", atom.get_property("Cartn_x") },
{ "Cartn_y", atom.get_property("Cartn_y") },
@@ -2216,7 +2216,7 @@ std::string structure::create_non_poly(const std::string &entity_id, const std::
{ "occupancy", atom.get_property("occupancy") },
{ "B_iso_or_equiv", atom.get_property("B_iso_or_equiv") },
{ "pdbx_formal_charge", atom.get_property("pdbx_formal_charge") },
{ "auth_seq_id", 1 },
{ "auth_seq_id", "1" },
{ "auth_comp_id", comp_id },
{ "auth_asym_id", asym_id },
{ "auth_atom_id", atom.get_property("label_atom_id") },
@@ -2232,13 +2232,13 @@ std::string structure::create_non_poly(const std::string &entity_id, const std::
{ "asym_id", asym_id },
{ "entity_id", entity_id },
{ "mon_id", comp_id },
{ "ndb_seq_num", ndb_nr },
{ "ndb_seq_num", std::to_string(ndb_nr) },
{ "pdb_seq_num", res.get_pdb_seq_num() },
{ "auth_seq_num", res.get_pdb_seq_num() },
{ "pdb_mon_id", comp_id },
{ "auth_mon_id", comp_id },
{ "pdb_strand_id", asym_id },
{ "pdb_ins_code", "." },
{ "pdb_ins_code", nullptr },
});
return asym_id;
@@ -2274,7 +2274,7 @@ std::string structure::create_non_poly(const std::string &entity_id, std::vector
atom.set_value_if_empty({ "group_PDB", "HETATM" });
atom.set_value_if_empty({ "label_comp_id", comp_id });
atom.set_value_if_empty({ "label_seq_id", "." });
atom.set_value_if_empty({ "label_seq_id", nullptr });
atom.set_value_if_empty({ "auth_comp_id", comp_id });
atom.set_value_if_empty({ "auth_seq_id", 1 });
atom.set_value_if_empty({ "pdbx_PDB_model_num", 1 });
@@ -2299,7 +2299,7 @@ std::string structure::create_non_poly(const std::string &entity_id, std::vector
{ "pdb_mon_id", comp_id },
{ "auth_mon_id", comp_id },
{ "pdb_strand_id", asym_id },
{ "pdb_ins_code", "." },
{ "pdb_ins_code", nullptr },
});
return asym_id;
@@ -2373,7 +2373,7 @@ void structure::create_water(row_initializer atom)
atom.set_value_if_empty({ "group_PDB", "HETATM" });
atom.set_value_if_empty({ "label_comp_id", "HOH" });
atom.set_value_if_empty({ "label_seq_id", "." });
atom.set_value_if_empty({ "label_seq_id", nullptr });
atom.set_value_if_empty({ "auth_comp_id", "HOH" });
atom.set_value_if_empty({ "pdbx_PDB_model_num", 1 });
atom.set_value_if_empty({ "label_alt_id", "" });
@@ -2395,7 +2395,7 @@ void structure::create_water(row_initializer atom)
{ "pdb_mon_id", "HOH" },
{ "auth_mon_id", "HOH" },
{ "pdb_strand_id", asym_id },
{ "pdb_ins_code", "." },
{ "pdb_ins_code", nullptr },
});
}
@@ -2508,7 +2508,7 @@ branch &structure::create_branch()
// // atom.set_value_if_empty({"group_PDB", "HETATM"});
// // atom.set_value_if_empty({"label_comp_id", "NAG"});
// // atom.set_value_if_empty({"label_seq_id", "."});
// // atom.set_value_if_empty({"label_seq_id", nullptr});
// // atom.set_value_if_empty({"auth_comp_id", "NAG"});
// // atom.set_value_if_empty({"pdbx_PDB_model_num", 1});
// // atom.set_value_if_empty({"label_alt_id", ""});

View File

@@ -2843,7 +2843,7 @@ int WriteHeterogen(std::ostream &pdbFile, const datablock &db)
std::string id, name, mon_nstd_flag;
cif::tie(id, name, mon_nstd_flag) = r.get("id", "name", "mon_nstd_flag");
if (mon_nstd_flag == "y")
if (iequals(mon_nstd_flag, "Y"))
continue;
het[id] = name;

View File

@@ -175,7 +175,7 @@ bool is_valid_pdbx_file(const file &file, const validator &validator, std::error
std::map<int, std::set<std::string>> mon_per_seq_id;
for (const auto &[num, mon_id, hetero] : entity_poly_seq.find<int, std::string, bool>("entity_id"_key == entity_id, "num", "mon_id", "hetero"))
for (const auto &[num, mon_id, hetero] : entity_poly_seq.find<int, std::string, std::string>("entity_id"_key == entity_id, "num", "mon_id", "hetero"))
{
mon_per_seq_id[num].emplace(mon_id);
@@ -193,7 +193,7 @@ bool is_valid_pdbx_file(const file &file, const validator &validator, std::error
}
}
for (const auto &[seq_id, mon_id, hetero] : pdbx_poly_seq_scheme.find<int, std::string, bool>("entity_id"_key == entity_id, "seq_id", "mon_id", "hetero"))
for (const auto &[seq_id, mon_id, hetero] : pdbx_poly_seq_scheme.find<int, std::string, std::string>("entity_id"_key == entity_id, "seq_id", "mon_id", "hetero"))
{
if (entity_poly_seq.count(
"entity_id"_key == entity_id and
@@ -204,7 +204,7 @@ bool is_valid_pdbx_file(const file &file, const validator &validator, std::error
throw std::runtime_error("For each pdbx_poly_seq/struct_asym record there should be exactly one entity_poly_seq record");
}
if ((mon_per_seq_id[seq_id].size() > 1) != hetero)
if ((mon_per_seq_id[seq_id].size() > 1) != iequals(hetero, "Y"))
throw std::runtime_error("Mismatch between the hetero flag in the poly seq schemes and the number residues per seq_id");
}

View File

@@ -3,6 +3,7 @@
#include "test-main.hpp"
#include <cif++/utilities.hpp>
#include <cif++/compound.hpp>
std::filesystem::path gTestDir = std::filesystem::current_path();
@@ -33,7 +34,7 @@ int main(int argc, char *argv[])
// initialize CCD location
cif::add_file_resource("components.cif", gTestDir / ".." / "rsrc" / "ccd-subset.cif");
// cif::compound_factory::instance().push_dictionary(gTestDir / "HEM.cif");
cif::compound_factory::instance().push_dictionary(gTestDir / "HEM.cif");
return session.run();
}

View File

@@ -181,7 +181,7 @@ TEST_CASE("item_0")
cif::item i1("v1", "tekst");
cif::item i2("v2", 2);
cif::item i3("v3", 3.0);
cif::item i4("v4", true);
// cif::item i4("v4", true);
cif::item i5("v5", nullptr);
static_assert(cif::IntegralType<int>);
@@ -190,14 +190,14 @@ TEST_CASE("item_0")
CHECK(i1.value().get<std::string>() == "tekst");
CHECK(i2.value().get<int>() == 2);
CHECK(i3.value().get<double>() == 3.0);
CHECK(i4.value().get<bool>() == true);
// CHECK(i4.value().get<bool>() == true);
CHECK(i5.value().is_null());
CHECK(i5.value().is_missing());
CHECK(i5.value().empty());
i2.value() = false;
CHECK(i2.value().type() == cif::item_value_type::INT);
CHECK(i2.value().get<bool>() == false);
// CHECK(i2.value().get<bool>() == false);
cif::item i6 = std::move(i1);
CHECK(i6.value().get<std::string>() == "tekst");