Commit 6a0b6b99 by Maarten L. Hekkelman

using index in category

parent 08dd9dd5
...@@ -370,8 +370,7 @@ if(ENABLE_TESTING) ...@@ -370,8 +370,7 @@ if(ENABLE_TESTING)
find_package(Boost REQUIRED headers) find_package(Boost REQUIRED headers)
list(APPEND CIFPP_tests unit-v2 unit-3d format model list(APPEND CIFPP_tests unit-v2 unit-3d format model rename-compound sugar
# rename-compound sugar
) )
foreach(CIFPP_TEST IN LISTS CIFPP_tests) foreach(CIFPP_TEST IN LISTS CIFPP_tests)
......
...@@ -159,6 +159,22 @@ class category ...@@ -159,6 +159,22 @@ class category
} }
// -------------------------------------------------------------------- // --------------------------------------------------------------------
// A category can have a key, as defined by the validator/dictionary
/// @brief The key type
using key_type = row_initializer;
/// @brief Return a row_handle for the row specified by \a key
/// @param key The value for the key, fields specified in the dictionary should have a value
/// @return The row found in the index, or an undefined row_handle
row_handle operator[](const key_type &key);
const row_handle operator[](const key_type &key) const
{
return const_cast<category *>(this)->operator[](key);
}
// --------------------------------------------------------------------
template <typename... Ts, typename... Ns> template <typename... Ts, typename... Ns>
iterator_proxy<const category, Ts...> rows(Ns... names) const iterator_proxy<const category, Ts...> rows(Ns... names) const
...@@ -335,7 +351,7 @@ class category ...@@ -335,7 +351,7 @@ class category
iterator emplace(row_initializer &&ri) iterator emplace(row_initializer &&ri)
{ {
return this->emplace(ri.m_items.begin(), ri.m_items.end()); return this->emplace(ri.begin(), ri.end());
} }
template <typename ItemIter> template <typename ItemIter>
......
...@@ -86,6 +86,18 @@ class file : public std::list<datablock> ...@@ -86,6 +86,18 @@ class file : public std::list<datablock>
bool contains(std::string_view name) const; bool contains(std::string_view name) const;
datablock &front()
{
assert(not empty());
return std::list<datablock>::front();
}
const datablock &front() const
{
assert(not empty());
return std::list<datablock>::front();
}
datablock &operator[](std::string_view name); datablock &operator[](std::string_view name);
const datablock &operator[](std::string_view name) const; const datablock &operator[](std::string_view name) const;
......
...@@ -34,19 +34,6 @@ ...@@ -34,19 +34,6 @@
#include <format> #include <format>
#endif #endif
/*
To modify a structure, you will have to use actions.
The currently supported actions are:
// - Move atom to new location
- Remove atom
// - Add new atom that was formerly missing
// - Add alternate residue
-
*/
namespace cif::mm namespace cif::mm
{ {
...@@ -63,10 +50,9 @@ class atom ...@@ -63,10 +50,9 @@ class atom
private: private:
struct atom_impl : public std::enable_shared_from_this<atom_impl> struct atom_impl : public std::enable_shared_from_this<atom_impl>
{ {
atom_impl(datablock &db, std::string_view id, row_handle row) atom_impl(datablock &db, std::string_view id)
: m_db(db) : m_db(db)
, m_id(id) , m_id(id)
, m_row(row)
{ {
prefetch(); prefetch();
} }
...@@ -84,95 +70,18 @@ class atom ...@@ -84,95 +70,18 @@ class atom
int get_charge() const; int get_charge() const;
void moveTo(const point &p) void moveTo(const point &p);
{
if (m_symop != "1_555")
throw std::runtime_error("Moving symmetry copy");
#if __cpp_lib_format
m_row.assign("Cartn_x", std::format("{:.3f}", p.getX()), false, false);
m_row.assign("Cartn_y", std::format("{:.3f}", p.getY()), false, false);
m_row.assign("Cartn_z", std::format("{:.3f}", p.getZ()), false, false);
#else
m_row.assign("Cartn_x", format("%.3f", p.m_x).str(), false, false);
m_row.assign("Cartn_y", format("%.3f", p.m_y).str(), false, false);
m_row.assign("Cartn_z", format("%.3f", p.m_z).str(), false, false);
#endif
m_location = p;
}
// const compound *compound() const; // const compound *compound() const;
std::string get_property(std::string_view name) const std::string get_property(std::string_view name) const;
{ int get_property_int(std::string_view name) const;
return m_row[name].as<std::string>(); float get_property_float(std::string_view name) const;
// for (auto &&[tag, ref] : mCachedRefs)
// {
// if (tag == name)
// return ref.as<std::string>();
// }
// mCachedRefs.emplace_back(name, const_cast<Row &>(mRow)[name]);
// return std::get<1>(mCachedRefs.back()).as<std::string>();
}
int get_property_int(std::string_view name) const void set_property(const std::string_view name, const std::string &value);
{
int result = 0;
if (not m_row[name].empty())
{
auto s = get_property(name);
std::from_chars_result r = std::from_chars(s.data(), s.data() + s.length(), result);
if (r.ec != std::errc() and VERBOSE > 0)
std::cerr << "Error converting " << s << " to number for property " << name << std::endl;
}
return result;
}
float get_property_float(std::string_view name) const
{
float result = 0;
if (not m_row[name].empty())
{
auto s = get_property(name);
std::from_chars_result r = std::from_chars(s.data(), s.data() + s.length(), result);
if (r.ec != std::errc() and VERBOSE > 0)
std::cerr << "Error converting " << s << " to number for property " << name << std::endl;
}
return result;
}
void set_property(const std::string_view name, const std::string &value)
{
m_row.assign(name, value, true, true);
}
// const datablock &m_db;
// std::string mID;
// atom_type mType;
// std::string mAtomID;
// std::string mCompID;
// std::string m_asym_id;
// int m_seq_id;
// std::string mAltID;
// std::string m_auth_seq_id;
// point mLocation;
// row_handle mRow;
// // mutable std::vector<std::tuple<std::string, detail::ItemReference>> mCachedRefs;
// mutable const compound *mcompound = nullptr;
// bool mSymmetryCopy = false;
// bool mClone = false;
const datablock &m_db; const datablock &m_db;
std::string m_id; std::string m_id;
row_handle m_row;
point m_location; point m_location;
std::string m_symop = "1_555"; std::string m_symop = "1_555";
}; };
...@@ -190,10 +99,10 @@ class atom ...@@ -190,10 +99,10 @@ class atom
{ {
} }
atom(datablock &db, row_handle &row) // atom(datablock &db, row_handle &row)
: atom(std::make_shared<atom_impl>(db, row["id"].as<std::string>(), row)) // : atom(std::make_shared<atom_impl>(db, row["id"].as<std::string>(), row))
{ // {
} // }
// a special constructor to create symmetry copies // a special constructor to create symmetry copies
atom(const atom &rhs, const point &symmmetry_location, const std::string &symmetry_operation) atom(const atom &rhs, const point &symmmetry_location, const std::string &symmetry_operation)
...@@ -897,10 +806,10 @@ class structure ...@@ -897,10 +806,10 @@ class structure
/// \param entity_id The entity ID of the new nonpoly /// \param entity_id The entity ID of the new nonpoly
/// \param atoms The array of sets of item data containing the data for the atoms. /// \param atoms The array of sets of item data containing the data for the atoms.
/// \return The newly create asym ID /// \return The newly create asym ID
std::string create_non_poly(const std::string &entity_id, std::vector<std::vector<item>> &atom_info); std::string create_non_poly(const std::string &entity_id, std::vector<row_initializer> atoms);
/// \brief Create a new (sugar) branch with one first NAG containing atoms constructed from \a nag_atom_info /// \brief Create a new (sugar) branch with one first NAG containing atoms constructed from \a atoms
branch &create_branch(std::vector<std::vector<item>> &nag_atom_info); branch &create_branch(std::vector<row_initializer> atoms);
/// \brief Extend an existing (sugar) branch identified by \a asymID with one sugar containing atoms constructed from \a atom_info /// \brief Extend an existing (sugar) branch identified by \a asymID with one sugar containing atoms constructed from \a atom_info
/// ///
...@@ -908,7 +817,7 @@ class structure ...@@ -908,7 +817,7 @@ class structure
/// \param atom_info Array containing the info for the atoms to construct for the new sugar /// \param atom_info Array containing the info for the atoms to construct for the new sugar
/// \param link_sugar The sugar to link to, note: this is the sugar number (1 based) /// \param link_sugar The sugar to link to, note: this is the sugar number (1 based)
/// \param link_atom The atom id of the atom linked in the sugar /// \param link_atom The atom id of the atom linked in the sugar
branch &extend_branch(const std::string &asym_id, std::vector<std::vector<item>> &atom_info, branch &extend_branch(const std::string &asym_id, std::vector<row_initializer> atom_info,
int link_sugar, const std::string &link_atom); int link_sugar, const std::string &link_atom);
/// \brief Remove \a branch /// \brief Remove \a branch
......
...@@ -277,7 +277,7 @@ class row_handle ...@@ -277,7 +277,7 @@ class row_handle
// -------------------------------------------------------------------- // --------------------------------------------------------------------
class row_initializer class row_initializer : public std::vector<item>
{ {
public: public:
friend class category; friend class category;
...@@ -289,20 +289,17 @@ class row_initializer ...@@ -289,20 +289,17 @@ class row_initializer
row_initializer &operator=(row_initializer &&) = default; row_initializer &operator=(row_initializer &&) = default;
row_initializer(std::initializer_list<item> items) row_initializer(std::initializer_list<item> items)
: m_items(items) : std::vector<item>(items)
{ {
} }
template <typename ItemIter, std::enable_if_t<std::is_same_v<typename ItemIter::value_type, item>, int> = 0> template <typename ItemIter, std::enable_if_t<std::is_same_v<typename ItemIter::value_type, item>, int> = 0>
row_initializer(ItemIter b, ItemIter e) row_initializer(ItemIter b, ItemIter e)
: m_items(b, e) : std::vector<item>(b, e)
{ {
} }
row_initializer(row_handle rh); row_initializer(row_handle rh);
private:
std::vector<item> m_items;
}; };
} // namespace cif } // namespace cif
\ No newline at end of file
...@@ -96,6 +96,32 @@ class row_comparator ...@@ -96,6 +96,32 @@ class row_comparator
return d; return d;
} }
int operator()(const row_initializer &a, const row *b) const
{
assert(b);
row_handle rhb(m_category, *b);
int d = 0, i = 0;
for (auto &c : m_comparator)
{
size_t k;
compareFunc f;
std::tie(k, f) = c;
std::string_view ka = a[i++].value();
std::string_view kb = rhb[k].text();
d = f(ka, kb);
if (d != 0)
break;
}
return d;
}
private: private:
typedef std::function<int(std::string_view, std::string_view)> compareFunc; typedef std::function<int(std::string_view, std::string_view)> compareFunc;
typedef std::tuple<size_t, compareFunc> key_comparator; typedef std::tuple<size_t, compareFunc> key_comparator;
...@@ -126,6 +152,7 @@ class category_index ...@@ -126,6 +152,7 @@ class category_index
} }
row *find(row *k) const; row *find(row *k) const;
row *find_by_value(row_initializer k) const;
void insert(row *r); void insert(row *r);
void erase(row *r); void erase(row *r);
...@@ -331,6 +358,37 @@ row *category_index::find(row *k) const ...@@ -331,6 +358,37 @@ row *category_index::find(row *k) const
return r ? r->m_row : nullptr; return r ? r->m_row : nullptr;
} }
row *category_index::find_by_value(row_initializer k) const
{
// sort the values in k first
row_initializer k2;
for (auto &f : m_category.key_field_indices())
{
std::string fld = fld=m_category.get_column_name(f);
auto ki = find_if(k.begin(), k.end(), [&fld](item &i) { return i.name() == fld; });
if (ki == k.end())
k2.emplace_back(fld, "");
else
k2.emplace_back(*ki);
}
const entry *r = m_root;
while (r != nullptr)
{
int d = m_row_comparator(k2, r->m_row);
if (d < 0)
r = r->m_left;
else if (d > 0)
r = r->m_right;
else
break;
}
return r ? r->m_row : nullptr;
}
void category_index::insert(row *k) void category_index::insert(row *k)
{ {
m_root = insert(m_root, k); m_root = insert(m_root, k);
...@@ -861,6 +919,17 @@ void category::validate_links() const ...@@ -861,6 +919,17 @@ void category::validate_links() const
// -------------------------------------------------------------------- // --------------------------------------------------------------------
row_handle category::operator[](const key_type &key)
{
if (m_index == nullptr)
throw std::logic_error("Category " + m_name + " does not have an index");
auto row = m_index->find_by_value(key);
return row != nullptr ? row_handle{ *this, *row } : row_handle{};
}
// --------------------------------------------------------------------
condition category::get_parents_condition(row_handle rh, const category &parentCat) const condition category::get_parents_condition(row_handle rh, const category &parentCat) const
{ {
if (m_validator == nullptr or m_cat_validator == nullptr) if (m_validator == nullptr or m_cat_validator == nullptr)
...@@ -1714,7 +1783,7 @@ void category::swap_item(size_t column_ix, row_handle &a, row_handle &b) ...@@ -1714,7 +1783,7 @@ void category::swap_item(size_t column_ix, row_handle &a, row_handle &b)
v->m_next = vb->m_next; v->m_next = vb->m_next;
vb->m_next = nullptr; vb->m_next = nullptr;
if (rb->m_tail = vb) if (rb->m_tail == vb)
rb->m_tail = v; rb->m_tail = v;
break; break;
......
...@@ -47,7 +47,7 @@ namespace cif::mm ...@@ -47,7 +47,7 @@ namespace cif::mm
atom::atom_impl::atom_impl(const atom_impl &impl, const point &loc, const std::string &sym_op) atom::atom_impl::atom_impl(const atom_impl &impl, const point &loc, const std::string &sym_op)
: m_db(impl.m_db) : m_db(impl.m_db)
, m_id(impl.m_id) , m_id(impl.m_id)
, m_row(impl.m_row) // , m_row(impl.m_row)
, m_location(loc) , m_location(loc)
, m_symop(sym_op) , m_symop(sym_op)
{ {
...@@ -55,7 +55,65 @@ atom::atom_impl::atom_impl(const atom_impl &impl, const point &loc, const std::s ...@@ -55,7 +55,65 @@ atom::atom_impl::atom_impl(const atom_impl &impl, const point &loc, const std::s
void atom::atom_impl::prefetch() void atom::atom_impl::prefetch()
{ {
tie(m_location.m_x, m_location.m_y, m_location.m_z) = m_row.get("Cartn_x", "Cartn_y", "Cartn_z"); // tie(m_location.m_x, m_location.m_y, m_location.m_z) = m_row.get("Cartn_x", "Cartn_y", "Cartn_z");
}
void atom::atom_impl::moveTo(const point &p)
{
// if (m_symop != "1_555")
// throw std::runtime_error("Moving symmetry copy");
// #if __cpp_lib_format
// m_row.assign("Cartn_x", std::format("{:.3f}", p.getX()), false, false);
// m_row.assign("Cartn_y", std::format("{:.3f}", p.getY()), false, false);
// m_row.assign("Cartn_z", std::format("{:.3f}", p.getZ()), false, false);
// #else
// m_row.assign("Cartn_x", format("%.3f", p.m_x).str(), false, false);
// m_row.assign("Cartn_y", format("%.3f", p.m_y).str(), false, false);
// m_row.assign("Cartn_z", format("%.3f", p.m_z).str(), false, false);
// #endif
// m_location = p;
}
// const compound *compound() const;
std::string atom::atom_impl::get_property(std::string_view name) const
{
// return m_row[name].as<std::string>();
}
int atom::atom_impl::get_property_int(std::string_view name) const
{
int result = 0;
// if (not m_row[name].empty())
// {
// auto s = get_property(name);
// std::from_chars_result r = std::from_chars(s.data(), s.data() + s.length(), result);
// if (r.ec != std::errc() and VERBOSE > 0)
// std::cerr << "Error converting " << s << " to number for property " << name << std::endl;
// }
return result;
}
float atom::atom_impl::get_property_float(std::string_view name) const
{
float result = 0;
// if (not m_row[name].empty())
// {
// auto s = get_property(name);
// std::from_chars_result r = std::from_chars(s.data(), s.data() + s.length(), result);
// if (r.ec != std::errc() and VERBOSE > 0)
// std::cerr << "Error converting " << s << " to number for property " << name << std::endl;
// }
return result;
}
void atom::atom_impl::set_property(const std::string_view name, const std::string &value)
{
// m_row.assign(name, value, true, true);
} }
// int atom::atom_impl::compare(const atom_impl &b) const // int atom::atom_impl::compare(const atom_impl &b) const
...@@ -92,17 +150,17 @@ void atom::atom_impl::prefetch() ...@@ -92,17 +150,17 @@ void atom::atom_impl::prefetch()
int atom::atom_impl::get_charge() const int atom::atom_impl::get_charge() const
{ {
auto formalCharge = m_row["pdbx_formal_charge"].as<std::optional<int>>(); // auto formalCharge = m_row["pdbx_formal_charge"].as<std::optional<int>>();
if (not formalCharge.has_value()) // if (not formalCharge.has_value())
{ // {
auto c = cif::compound_factory::instance().create(get_property("label_comp_id")); // auto c = cif::compound_factory::instance().create(get_property("label_comp_id"));
if (c != nullptr and c->atoms().size() == 1) // if (c != nullptr and c->atoms().size() == 1)
formalCharge = c->atoms().front().charge; // formalCharge = c->atoms().front().charge;
} // }
return formalCharge.value_or(0); // return formalCharge.value_or(0);
} }
// const Compound *atom::atom_impl::compound() const // const Compound *atom::atom_impl::compound() const
...@@ -919,12 +977,14 @@ polymer::polymer(const structure &s, const std::string &entityID, const std::str ...@@ -919,12 +977,14 @@ polymer::polymer(const structure &s, const std::string &entityID, const std::str
, m_asym_id(asym_id) , m_asym_id(asym_id)
// , mPolySeq(s.m_db["pdbx_poly_seq_scheme"), key("asym_id") == m_asym_id and key("entity_id") == m_entity_i]) // , mPolySeq(s.m_db["pdbx_poly_seq_scheme"), key("asym_id") == m_asym_id and key("entity_id") == m_entity_i])
{ {
using namespace cif::literals;
std::map<size_t, size_t> ix; std::map<size_t, size_t> ix;
auto &poly_seq_scheme = s.get_datablock()["pdbx_poly_seq_scheme"]; auto &poly_seq_scheme = s.get_datablock()["pdbx_poly_seq_scheme"];
reserve(poly_seq_scheme.size()); reserve(poly_seq_scheme.size());
for (auto r : poly_seq_scheme) for (auto r : poly_seq_scheme.find("asym_id"_key == asym_id))
{ {
int seqID; int seqID;
std::string compoundID, authSeqID; std::string compoundID, authSeqID;
...@@ -1251,7 +1311,7 @@ void structure::load_atoms_for_model(StructureOpenOptions options) ...@@ -1251,7 +1311,7 @@ void structure::load_atoms_for_model(StructureOpenOptions options)
if ((options bitand StructureOpenOptions::SkipHydrogen) and type_symbol == "H") if ((options bitand StructureOpenOptions::SkipHydrogen) and type_symbol == "H")
continue; continue;
emplace_atom(std::make_shared<atom::atom_impl>(m_db, id, a)); emplace_atom(std::make_shared<atom::atom_impl>(m_db, id));
} }
} }
...@@ -1689,6 +1749,14 @@ atom &structure::emplace_atom(atom &&atom) ...@@ -1689,6 +1749,14 @@ atom &structure::emplace_atom(atom &&atom)
m_atom_index.insert(m_atom_index.begin() + R + 1, m_atoms.size()); m_atom_index.insert(m_atom_index.begin() + R + 1, m_atoms.size());
// make sure the atom_type is known
auto &atom_type = m_db["atom_type"];
std::string symbol = atom.get_property("type_symbol");
using namespace cif::literals;
if (not atom_type.exists("symbol"_key == symbol))
atom_type.emplace({ { "symbol", symbol } });
return m_atoms.emplace_back(std::move(atom)); return m_atoms.emplace_back(std::move(atom));
} }
...@@ -2088,7 +2156,7 @@ std::string structure::create_non_poly(const std::string &entity_id, const std:: ...@@ -2088,7 +2156,7 @@ std::string structure::create_non_poly(const std::string &entity_id, const std::
{"pdbx_PDB_model_num", 1} {"pdbx_PDB_model_num", 1}
}); });
auto &newAtom = emplace_atom(std::make_shared<atom::atom_impl>(m_db, atom_id, row)); auto &newAtom = emplace_atom(std::make_shared<atom::atom_impl>(m_db, atom_id));
res.add_atom(newAtom); res.add_atom(newAtom);
} }
...@@ -2110,7 +2178,7 @@ std::string structure::create_non_poly(const std::string &entity_id, const std:: ...@@ -2110,7 +2178,7 @@ std::string structure::create_non_poly(const std::string &entity_id, const std::
return asym_id; return asym_id;
} }
std::string structure::create_non_poly(const std::string &entity_id, std::vector<std::vector<item>> &atom_info) std::string structure::create_non_poly(const std::string &entity_id, std::vector<row_initializer> atoms)
{ {
using namespace literals; using namespace literals;
...@@ -2131,14 +2199,14 @@ std::string structure::create_non_poly(const std::string &entity_id, std::vector ...@@ -2131,14 +2199,14 @@ std::string structure::create_non_poly(const std::string &entity_id, std::vector
auto &res = m_non_polymers.emplace_back(*this, comp_id, asym_id, 0, "1"); auto &res = m_non_polymers.emplace_back(*this, comp_id, asym_id, 0, "1");
auto appendUnlessSet = [](std::vector<item> &ai, item &&i) auto appendUnlessSet = [](row_initializer &ai, item &&i)
{ {
if (find_if(ai.begin(), ai.end(), [name = i.name()](item &ci) if (find_if(ai.begin(), ai.end(), [name = i.name()](item &ci)
{ return ci.name() == name; }) == ai.end()) { return ci.name() == name; }) == ai.end())
ai.emplace_back(std::move(i)); ai.emplace_back(std::move(i));
}; };
for (auto &atom : atom_info) for (auto &atom : atoms)
{ {
auto atom_id = atom_site.get_unique_id(""); auto atom_id = atom_site.get_unique_id("");
...@@ -2156,7 +2224,7 @@ std::string structure::create_non_poly(const std::string &entity_id, std::vector ...@@ -2156,7 +2224,7 @@ std::string structure::create_non_poly(const std::string &entity_id, std::vector
auto row = atom_site.emplace(atom.begin(), atom.end()); auto row = atom_site.emplace(atom.begin(), atom.end());
auto &newAtom = emplace_atom(std::make_shared<atom::atom_impl>(m_db, atom_id, row)); auto &newAtom = emplace_atom(std::make_shared<atom::atom_impl>(m_db, atom_id));
res.add_atom(newAtom); res.add_atom(newAtom);
} }
...@@ -2178,10 +2246,10 @@ std::string structure::create_non_poly(const std::string &entity_id, std::vector ...@@ -2178,10 +2246,10 @@ std::string structure::create_non_poly(const std::string &entity_id, std::vector
return asym_id; return asym_id;
} }
branch &structure::create_branch(std::vector<std::vector<item>> &nag_atoms) branch &structure::create_branch(std::vector<row_initializer> atoms)
{ {
// sanity check // sanity check
for (auto &nag_atom : nag_atoms) for (auto &nag_atom : atoms)
{ {
for (auto info : nag_atom) for (auto info : nag_atom)
{ {
...@@ -2201,14 +2269,14 @@ branch &structure::create_branch(std::vector<std::vector<item>> &nag_atoms) ...@@ -2201,14 +2269,14 @@ branch &structure::create_branch(std::vector<std::vector<item>> &nag_atoms)
auto &atom_site = m_db["atom_site"]; auto &atom_site = m_db["atom_site"];
auto appendUnlessSet = [](std::vector<item> &ai, item &&i) auto appendUnlessSet = [](row_initializer &ai, item &&i)
{ {
if (find_if(ai.begin(), ai.end(), [name = i.name()](item &ci) if (find_if(ai.begin(), ai.end(), [name = i.name()](item &ci)
{ return ci.name() == name; }) == ai.end()) { return ci.name() == name; }) == ai.end())
ai.emplace_back(std::move(i)); ai.emplace_back(std::move(i));
}; };
for (auto &atom : nag_atoms) for (auto &atom : atoms)
{ {
auto atom_id = atom_site.get_unique_id(""); auto atom_id = atom_site.get_unique_id("");
...@@ -2226,7 +2294,7 @@ branch &structure::create_branch(std::vector<std::vector<item>> &nag_atoms) ...@@ -2226,7 +2294,7 @@ branch &structure::create_branch(std::vector<std::vector<item>> &nag_atoms)
auto row = atom_site.emplace(atom.begin(), atom.end()); auto row = atom_site.emplace(atom.begin(), atom.end());
auto &newAtom = emplace_atom(std::make_shared<atom::atom_impl>(m_db, atom_id, row)); auto &newAtom = emplace_atom(std::make_shared<atom::atom_impl>(m_db, atom_id));
sugar.add_atom(newAtom); sugar.add_atom(newAtom);
} }
...@@ -2265,7 +2333,7 @@ branch &structure::create_branch(std::vector<std::vector<item>> &nag_atoms) ...@@ -2265,7 +2333,7 @@ branch &structure::create_branch(std::vector<std::vector<item>> &nag_atoms)
return branch; return branch;
} }
branch &structure::extend_branch(const std::string &asym_id, std::vector<std::vector<item>> &atom_info, branch &structure::extend_branch(const std::string &asym_id, std::vector<row_initializer> atom_info,
int link_sugar, const std::string &link_atom) int link_sugar, const std::string &link_atom)
{ {
// sanity check // sanity check
......
...@@ -69,7 +69,7 @@ row_initializer::row_initializer(row_handle rh) ...@@ -69,7 +69,7 @@ row_initializer::row_initializer(row_handle rh)
auto &cat = *rh.m_category; auto &cat = *rh.m_category;
for (auto i = r->m_head; i != nullptr; i = i->m_next) for (auto i = r->m_head; i != nullptr; i = i->m_next)
m_items.emplace_back(cat.get_column_name(i->m_column_ix), i->text()); emplace_back(cat.get_column_name(i->m_column_ix), i->text());
} }
} // namespace cif } // namespace cif
\ No newline at end of file
...@@ -177,6 +177,7 @@ _struct_asym.pdbx_blank_PDB_chainid_flag N ...@@ -177,6 +177,7 @@ _struct_asym.pdbx_blank_PDB_chainid_flag N
_struct_asym.pdbx_modified N _struct_asym.pdbx_modified N
_struct_asym.details ? _struct_asym.details ?
# #
_atom_type.symbol C
)"_cf; )"_cf;
expected.load_dictionary("mmcif_pdbx.dic"); expected.load_dictionary("mmcif_pdbx.dic");
......
#include "../include/cif++/Cif++.hpp" /*-
#include "../include/cif++/PDB2Cif.hpp" * SPDX-License-Identifier: BSD-2-Clause
#include "../include/cif++/Structure.hpp" *
* Copyright (c) 2021 NKI/AVL, Netherlands Cancer Institute
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <cif++.hpp>
#include <iostream> #include <iostream>
#include <fstream> #include <fstream>
...@@ -22,16 +46,16 @@ int main(int argc, char* argv[]) ...@@ -22,16 +46,16 @@ int main(int argc, char* argv[])
if (std::filesystem::exists(testdir / ".." / "rsrc" / "mmcif_pdbx.dic")) if (std::filesystem::exists(testdir / ".." / "rsrc" / "mmcif_pdbx.dic"))
cif::add_file_resource("mmcif_pdbx.dic", testdir / ".." / "rsrc" / "mmcif_pdbx.dic"); cif::add_file_resource("mmcif_pdbx.dic", testdir / ".." / "rsrc" / "mmcif_pdbx.dic");
mmcif::CompoundFactory::instance().pushDictionary(testdir / "REA.cif"); cif::compound_factory::instance().push_dictionary(testdir / "REA.cif");
mmcif::CompoundFactory::instance().pushDictionary(testdir / "RXA.cif"); cif::compound_factory::instance().push_dictionary(testdir / "RXA.cif");
mmcif::file f(testdir / ".."/"examples"/"1cbs.cif.gz"); cif::file f(testdir / ".."/"examples"/"1cbs.cif.gz");
mmcif::Structure structure(f); cif::mm::structure structure(f);
auto &res = structure.getResidue("B"); auto &res = structure.get_residue("B");
structure.change_residue(res, "RXA", {}); structure.change_residue(res, "RXA", {});
structure.cleanupEmptyCategories(); structure.cleanup_empty_categories();
f.save(std::cout); f.save(std::cout);
} }
......
...@@ -29,8 +29,7 @@ ...@@ -29,8 +29,7 @@
#include <stdexcept> #include <stdexcept>
#include <cif++/cif.hpp> #include <cif++.hpp>
#include <cif++/structure/Structure.hpp>
// -------------------------------------------------------------------- // --------------------------------------------------------------------
...@@ -66,7 +65,7 @@ bool init_unit_test() ...@@ -66,7 +65,7 @@ bool init_unit_test()
// initialize CCD location // initialize CCD location
cif::add_file_resource("components.cif", gTestDir / ".." / "data" / "ccd-subset.cif"); cif::add_file_resource("components.cif", gTestDir / ".." / "data" / "ccd-subset.cif");
mmcif::CompoundFactory::instance().pushDictionary(gTestDir / "HEM.cif"); cif::compound_factory::instance().push_dictionary(gTestDir / "HEM.cif");
return true; return true;
} }
...@@ -78,10 +77,10 @@ BOOST_AUTO_TEST_CASE(sugar_name_1) ...@@ -78,10 +77,10 @@ BOOST_AUTO_TEST_CASE(sugar_name_1)
using namespace cif::literals; using namespace cif::literals;
const std::filesystem::path example(gTestDir / "1juh.cif.gz"); const std::filesystem::path example(gTestDir / "1juh.cif.gz");
mmcif::file file(example.string()); cif::file file(example.string());
mmcif::Structure s(file); cif::mm::structure s(file);
auto &db = s.datablock(); auto &db = s.get_datablock();
auto &entity = db["entity"]; auto &entity = db["entity"];
auto &branches = s.branches(); auto &branches = s.branches();
...@@ -90,7 +89,7 @@ BOOST_AUTO_TEST_CASE(sugar_name_1) ...@@ -90,7 +89,7 @@ BOOST_AUTO_TEST_CASE(sugar_name_1)
for (auto &branch : branches) for (auto &branch : branches)
{ {
auto entityID = branch.front().entityID(); auto entityID = branch.front().get_entity_id();
auto name = entity.find1<std::string>("id"_key == entityID, "pdbx_description"); auto name = entity.find1<std::string>("id"_key == entityID, "pdbx_description");
BOOST_CHECK_EQUAL(branch.name(), name); BOOST_CHECK_EQUAL(branch.name(), name);
...@@ -104,20 +103,20 @@ BOOST_AUTO_TEST_CASE(create_sugar_1) ...@@ -104,20 +103,20 @@ BOOST_AUTO_TEST_CASE(create_sugar_1)
using namespace cif::literals; using namespace cif::literals;
const std::filesystem::path example(gTestDir / "1juh.cif.gz"); const std::filesystem::path example(gTestDir / "1juh.cif.gz");
mmcif::file file(example.string()); cif::file file(example.string());
mmcif::Structure s(file); cif::mm::structure s(file);
// collect atoms from asym L first // collect atoms from asym L first
auto &NAG = s.getResidue("L"); auto &NAG = s.get_residue("L");
auto nagAtoms = NAG.atoms(); auto nagAtoms = NAG.atoms();
std::vector<std::vector<cif::Item>> ai; std::vector<cif::row_initializer> ai;
auto &db = s.datablock(); auto &db = s.get_datablock();
auto &as = db["atom_site"]; auto &as = db["atom_site"];
for (auto r : as.find("label_asym_id"_key == "L")) for (auto r : as.find("label_asym_id"_key == "L"))
ai.emplace_back(r.begin(), r.end()); ai.emplace_back(r);
s.remove_residue(NAG); s.remove_residue(NAG);
...@@ -136,36 +135,36 @@ BOOST_AUTO_TEST_CASE(create_sugar_2) ...@@ -136,36 +135,36 @@ BOOST_AUTO_TEST_CASE(create_sugar_2)
using namespace cif::literals; using namespace cif::literals;
const std::filesystem::path example(gTestDir / "1juh.cif.gz"); const std::filesystem::path example(gTestDir / "1juh.cif.gz");
mmcif::file file(example.string()); cif::file file(example.string());
mmcif::Structure s(file); cif::mm::structure s(file);
// Get branch for H // Get branch for H
auto &bH = s.getBranchByAsymID("H"); auto &bH = s.get_branch_by_asym_id("H");
BOOST_CHECK_EQUAL(bH.size(), 2); BOOST_CHECK_EQUAL(bH.size(), 2);
std::vector<std::vector<cif::Item>> ai[2]; std::vector<cif::row_initializer> ai[2];
auto &db = s.datablock(); auto &db = s.get_datablock();
auto &as = db["atom_site"]; auto &as = db["atom_site"];
for (size_t i = 0; i < 2; ++i) for (size_t i = 0; i < 2; ++i)
{ {
for (auto r : as.find("label_asym_id"_key == "H" and "auth_seq_id"_key == i + 1)) for (auto r : as.find("label_asym_id"_key == "H" and "auth_seq_id"_key == i + 1))
ai[i].emplace_back(r.begin(), r.end()); ai[i].emplace_back(r);
} }
s.remove_branch(bH); s.remove_branch(bH);
auto &bN = s.create_branch(ai[0]); auto &bN = s.create_branch(ai[0]);
s.extend_branch(bN.asymID(), ai[1], 1, "O4"); s.extend_branch(bN.get_asym_id(), ai[1], 1, "O4");
BOOST_CHECK_EQUAL(bN.name(), "2-acetamido-2-deoxy-beta-D-glucopyranose-(1-4)-2-acetamido-2-deoxy-beta-D-glucopyranose"); BOOST_CHECK_EQUAL(bN.name(), "2-acetamido-2-deoxy-beta-D-glucopyranose-(1-4)-2-acetamido-2-deoxy-beta-D-glucopyranose");
BOOST_CHECK_EQUAL(bN.size(), 2); BOOST_CHECK_EQUAL(bN.size(), 2);
file.save(gTestDir / "test-create_sugar_2.cif"); file.save(gTestDir / "test-create_sugar_2.cif");
BOOST_CHECK_NO_THROW(mmcif::Structure s2(file)); BOOST_CHECK_NO_THROW(cif::mm::structure s2(file));
} }
// -------------------------------------------------------------------- // --------------------------------------------------------------------
...@@ -175,11 +174,11 @@ BOOST_AUTO_TEST_CASE(delete_sugar_1) ...@@ -175,11 +174,11 @@ BOOST_AUTO_TEST_CASE(delete_sugar_1)
using namespace cif::literals; using namespace cif::literals;
const std::filesystem::path example(gTestDir / "1juh.cif.gz"); const std::filesystem::path example(gTestDir / "1juh.cif.gz");
mmcif::file file(example.string()); cif::file file(example.string());
mmcif::Structure s(file); cif::mm::structure s(file);
// Get branch for H // Get branch for H
auto &bG = s.getBranchByAsymID("G"); auto &bG = s.get_branch_by_asym_id("G");
BOOST_CHECK_EQUAL(bG.size(), 4); BOOST_CHECK_EQUAL(bG.size(), 4);
...@@ -187,12 +186,12 @@ BOOST_AUTO_TEST_CASE(delete_sugar_1) ...@@ -187,12 +186,12 @@ BOOST_AUTO_TEST_CASE(delete_sugar_1)
BOOST_CHECK_EQUAL(bG.size(), 1); BOOST_CHECK_EQUAL(bG.size(), 1);
auto &bN = s.getBranchByAsymID("G"); auto &bN = s.get_branch_by_asym_id("G");
BOOST_CHECK_EQUAL(bN.name(), "2-acetamido-2-deoxy-beta-D-glucopyranose"); BOOST_CHECK_EQUAL(bN.name(), "2-acetamido-2-deoxy-beta-D-glucopyranose");
BOOST_CHECK_EQUAL(bN.size(), 1); BOOST_CHECK_EQUAL(bN.size(), 1);
file.save(gTestDir / "test-create_sugar_3.cif"); file.save(gTestDir / "test-create_sugar_3.cif");
BOOST_CHECK_NO_THROW(mmcif::Structure s2(file)); BOOST_CHECK_NO_THROW(cif::mm::structure s2(file));
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment