Commit c3434507 by Maarten L. Hekkelman

new find1

parent 79ecf20b
...@@ -1903,19 +1903,39 @@ class Category ...@@ -1903,19 +1903,39 @@ class Category
return *h.begin(); return *h.begin();
} }
template <typename... Ts, size_t N> template <typename T>
std::tuple<Ts...> find1(Condition &&cond, char const *const (&columns)[N]) T find1(Condition &&cond, const char* column)
{ {
static_assert(sizeof...(Ts) == N, "The number of column titles should be equal to the number of types to return"); return find1<T>(cbegin(), std::forward<Condition>(cond), column);
return find1<Ts...>(cbegin(), std::forward<Condition>(cond), std::forward<char const *const[N]>(columns));
} }
template <typename... Ts, size_t N> template <typename T>
std::tuple<Ts...> find1(const_iterator pos, Condition &&cond, char const *const (&columns)[N]) T find1(const_iterator pos, Condition &&cond, const char* column)
{ {
static_assert(sizeof...(Ts) == N, "The number of column titles should be equal to the number of types to return"); auto h = find<T>(pos, std::forward<Condition>(cond), { column });
if (h.empty())
throw std::runtime_error("No hits found");
auto h = find<Ts...>(pos, std::forward<Condition>(cond), std::forward<char const *const[N]>(columns)); if (h.size() != 1)
throw std::runtime_error("Hit not unique");
return std::get<0>(*h.begin());
}
template <typename... Ts, typename... Cs, typename U = std::enable_if_t<sizeof...(Ts) != 1>>
std::tuple<Ts...> find1(Condition &&cond, Cs... columns)
{
static_assert(sizeof...(Ts) == sizeof...(Cs), "The number of column titles should be equal to the number of types to return");
// static_assert(std::is_same_v<Cs, const char*>..., "The column names should be const char");
return find1<Ts...>(cbegin(), std::forward<Condition>(cond), std::forward<Cs>(columns)...);
}
template <typename... Ts, typename... Cs, typename U = std::enable_if_t<sizeof...(Ts) != 1>>
std::tuple<Ts...> find1(const_iterator pos, Condition &&cond, Cs... columns)
{
static_assert(sizeof...(Ts) == sizeof...(Cs), "The number of column titles should be equal to the number of types to return");
auto h = find<Ts...>(pos, std::forward<Condition>(cond), { columns... });
if (h.empty()) if (h.empty())
throw std::runtime_error("No hits found"); throw std::runtime_error("No hits found");
......
...@@ -485,11 +485,9 @@ class Structure ...@@ -485,11 +485,9 @@ class Structure
const std::vector<std::tuple<std::string, std::string>> &remappedAtoms); const std::vector<std::tuple<std::string, std::string>> &remappedAtoms);
/// \brief Create a new non-polymer entity, returns new ID /// \brief Create a new non-polymer entity, returns new ID
/// \param data The data to use to fill the entity /// \param mon_id The mon_id for the new nonpoly, must be an existing and known compound from CCD
/// \param mon_id The mon_id for the new nonpoly
/// \param name The name of the nonpoly
/// \return The ID of the created entity /// \return The ID of the created entity
std::string createEntityNonPoly(std::vector<cif::Item> data, const std::string &mon_id); std::string createEntityNonPoly(const std::string &mon_id);
/// \brief Create a new NonPolymer struct_asym with atoms constructed from \a atom_data, returns asym_id /// \brief Create a new NonPolymer struct_asym with atoms constructed from \a atom_data, returns asym_id
/// \param entity_id The entity ID of the new nonpoly /// \param entity_id The entity ID of the new nonpoly
...@@ -515,7 +513,7 @@ class Structure ...@@ -515,7 +513,7 @@ class Structure
cif::Category &category(const char *name) const; cif::Category &category(const char *name) const;
cif::Datablock &datablock() const; cif::Datablock &datablock() const;
void insertCompound(const std::string &compoundID, bool isEntity); std::string insertCompound(const std::string &compoundID, bool isEntity);
void loadData(); void loadData();
void updateAtomIndex(); void updateAtomIndex();
......
...@@ -2161,8 +2161,10 @@ cif::Datablock &Structure::datablock() const ...@@ -2161,8 +2161,10 @@ cif::Datablock &Structure::datablock() const
return *mFile.impl().mDb; return *mFile.impl().mDb;
} }
void Structure::insertCompound(const std::string &compoundID, bool isEntity) std::string Structure::insertCompound(const std::string &compoundID, bool isEntity)
{ {
using namespace cif::literals;
auto compound = CompoundFactory::instance().create(compoundID); auto compound = CompoundFactory::instance().create(compoundID);
if (compound == nullptr) if (compound == nullptr)
throw std::runtime_error("Trying to insert unknown compound " + compoundID + " (not found in CCD)"); throw std::runtime_error("Trying to insert unknown compound " + compoundID + " (not found in CCD)");
...@@ -2173,31 +2175,42 @@ void Structure::insertCompound(const std::string &compoundID, bool isEntity) ...@@ -2173,31 +2175,42 @@ void Structure::insertCompound(const std::string &compoundID, bool isEntity)
auto r = chemComp.find(cif::Key("id") == compoundID); auto r = chemComp.find(cif::Key("id") == compoundID);
if (r.empty()) if (r.empty())
{ {
chemComp.emplace({{"id", compoundID}, chemComp.emplace({
{"id", compoundID},
{"name", compound->name()}, {"name", compound->name()},
{"formula", compound->formula()}, {"formula", compound->formula()},
{"formula_weight", compound->formulaWeight()}, {"formula_weight", compound->formulaWeight()},
{"type", compound->type()}}); {"type", compound->type()}});
} }
std::string entity_id;
if (isEntity) if (isEntity)
{ {
auto &pdbxEntityNonpoly = db["pdbx_entity_nonpoly"]; auto &pdbxEntityNonpoly = db["pdbx_entity_nonpoly"];
if (not pdbxEntityNonpoly.exists(cif::Key("comp_id") == compoundID)) try
{
entity_id = pdbxEntityNonpoly.find1<std::string>("comp_id"_key == compoundID, "entity_id");
}
catch(const std::exception& ex)
{ {
auto &entity = db["entity"]; auto &entity = db["entity"];
std::string entityID = std::to_string(entity.size() + 1); entity_id = std::to_string(entity.size() + 1);
entity.emplace({{"id", entityID}, entity.emplace({
{"id", entity_id},
{"type", "non-polymer"}, {"type", "non-polymer"},
{"pdbx_description", compound->name()}, {"pdbx_description", compound->name()},
{"formula_weight", compound->formulaWeight()}}); {"formula_weight", compound->formulaWeight()}});
pdbxEntityNonpoly.emplace({{"entity_id", entityID}, pdbxEntityNonpoly.emplace({
{"entity_id", entity_id},
{"name", compound->name()}, {"name", compound->name()},
{"comp_id", compoundID}}); {"comp_id", compoundID}});
} }
} }
return entity_id;
} }
// // -------------------------------------------------------------------- // // --------------------------------------------------------------------
...@@ -2340,7 +2353,7 @@ void Structure::changeResidue(const Residue &res, const std::string &newCompound ...@@ -2340,7 +2353,7 @@ void Structure::changeResidue(const Residue &res, const std::string &newCompound
try try
{ {
std::tie(entityID) = entity.find1<std::string>("type"_key == "non-polymer" and "pdbx_description"_key == compound->name(), {"id"}); entityID = entity.find1<std::string>("type"_key == "non-polymer" and "pdbx_description"_key == compound->name(), "id");
} }
catch (const std::exception &ex) catch (const std::exception &ex)
{ {
...@@ -2413,35 +2426,9 @@ void Structure::changeResidue(const Residue &res, const std::string &newCompound ...@@ -2413,35 +2426,9 @@ void Structure::changeResidue(const Residue &res, const std::string &newCompound
} }
} }
std::string Structure::createEntityNonPoly(std::vector<cif::Item> data, const std::string &comp_id) std::string Structure::createEntityNonPoly(const std::string &comp_id)
{ {
using namespace cif::literals; return insertCompound(comp_id, true);
auto &db = mFile.data();
auto &entity = db["entity"];
std::string entity_id = entity.getUniqueID("");
// remove any ID fields
data.erase(std::remove_if(data.begin(), data.end(), [](cif::Item &item) { return item.name() == "id"; }),
data.end());
// add our new ID
data.emplace_back("id", entity_id);
data.emplace_back("type", "non-polymer");
entity.emplace(data.begin(), data.end());
const auto &[ name ] = entity.find1<std::string>("id"_key == entity_id, { "pdbx_description" });
auto &pdbx_entity_nonpoly = db["pdbx_entity_nonpoly"];
pdbx_entity_nonpoly.emplace({
{ "entity_id", entity_id },
{ "name", name },
{ "comp_id", comp_id }
});
return entity_id;
} }
std::string Structure::createNonpoly(const std::string &entity_id, const std::vector<cif::Item> &atoms) std::string Structure::createNonpoly(const std::string &entity_id, const std::vector<cif::Item> &atoms)
......
...@@ -59,18 +59,22 @@ BOOST_AUTO_TEST_CASE(create_nonpoly_1) ...@@ -59,18 +59,22 @@ BOOST_AUTO_TEST_CASE(create_nonpoly_1)
auto expected = R"( auto expected = R"(
data_TEST data_TEST
loop_ #
_entity.id _chem_comp.id HEM
_entity.type _chem_comp.type NON-POLYMER
_entity.src_method _chem_comp.name 'PROTOPORPHYRIN IX CONTAINING FE'
_entity.pdbx_description _chem_comp.formula 'C34 H32 Fe N4 O4'
_entity.formula_weight _chem_comp.formula_weight 616.487000
1 non-polymer syn 'PROTOPORPHYRIN IX CONTAINING FE' 616.487 #
loop_ _pdbx_entity_nonpoly.entity_id 1
_pdbx_entity_nonpoly.entity_id _pdbx_entity_nonpoly.name 'PROTOPORPHYRIN IX CONTAINING FE'
_pdbx_entity_nonpoly.name _pdbx_entity_nonpoly.comp_id HEM
_pdbx_entity_nonpoly.comp_id #
1 'PROTOPORPHYRIN IX CONTAINING FE' HEM _entity.id 1
_entity.type non-polymer
_entity.pdbx_description 'PROTOPORPHYRIN IX CONTAINING FE'
_entity.formula_weight 616.487000
#
)"_cf; )"_cf;
expected.loadDictionary("mmcif_pdbx_v50.dic"); expected.loadDictionary("mmcif_pdbx_v50.dic");
...@@ -81,11 +85,7 @@ _pdbx_entity_nonpoly.comp_id ...@@ -81,11 +85,7 @@ _pdbx_entity_nonpoly.comp_id
mmcif::Structure structure(file); mmcif::Structure structure(file);
structure.createEntityNonPoly({ structure.createEntityNonPoly("HEM");
{ "src_method", "syn" },
{ "pdbx_description", "PROTOPORPHYRIN IX CONTAINING FE" },
{ "formula_weight", 616.487 }
}, "HEM" );
if (not (expected.firstDatablock() == structure.getFile().data())) if (not (expected.firstDatablock() == structure.getFile().data()))
{ {
...@@ -94,38 +94,4 @@ _pdbx_entity_nonpoly.comp_id ...@@ -94,38 +94,4 @@ _pdbx_entity_nonpoly.comp_id
<< std::endl << std::endl
<< structure.getFile().data() << std::endl; << structure.getFile().data() << std::endl;
} }
// // using namespace mmcif;
// auto f = R"(data_TEST
// #
// loop_
// _test.id
// _test.name
// 1 aap
// 2 noot
// 3 mies
// )"_cf;
// auto& db = f.firstDatablock();
// BOOST_CHECK(db.getName() == "TEST");
// auto& test = db["test"];
// BOOST_CHECK(test.size() == 3);
// // wrong! the next lines will crash. And that's OK, don't do that
// // for (auto r: test)
// // test.erase(r);
// // BOOST_CHECK(test.empty());
// // test.purge();
// auto n = test.erase(cif::Key("id") == 1, [](const cif::Row& r) {
// BOOST_CHECK_EQUAL(r["id"].as<int>(), 1);
// BOOST_CHECK_EQUAL(r["name"].as<std::string>(), "aap");
// });
// BOOST_CHECK_EQUAL(n, 1);
} }
...@@ -1207,7 +1207,7 @@ _test.name ...@@ -1207,7 +1207,7 @@ _test.name
} }
} }
const auto& [id, name] = db["test"].find1<int, std::string>(cif::Key("id") == 1, { "id", "name" }); const auto& [id, name] = db["test"].find1<int, std::string>(cif::Key("id") == 1, "id", "name");
BOOST_CHECK(id == 1); BOOST_CHECK(id == 1);
BOOST_CHECK(name == "aap"); BOOST_CHECK(name == "aap");
......
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