Commit c3434507 by Maarten L. Hekkelman

new find1

parent 79ecf20b
......@@ -1903,19 +1903,39 @@ class Category
return *h.begin();
}
template <typename... Ts, size_t N>
std::tuple<Ts...> find1(Condition &&cond, char const *const (&columns)[N])
template <typename T>
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<Ts...>(cbegin(), std::forward<Condition>(cond), std::forward<char const *const[N]>(columns));
return find1<T>(cbegin(), std::forward<Condition>(cond), column);
}
template <typename... Ts, size_t N>
std::tuple<Ts...> find1(const_iterator pos, Condition &&cond, char const *const (&columns)[N])
template <typename T>
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())
throw std::runtime_error("No hits found");
......
......@@ -485,11 +485,9 @@ class Structure
const std::vector<std::tuple<std::string, std::string>> &remappedAtoms);
/// \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
/// \param name The name of the nonpoly
/// \param mon_id The mon_id for the new nonpoly, must be an existing and known compound from CCD
/// \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
/// \param entity_id The entity ID of the new nonpoly
......@@ -515,7 +513,7 @@ class Structure
cif::Category &category(const char *name) 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 updateAtomIndex();
......
......@@ -2161,8 +2161,10 @@ cif::Datablock &Structure::datablock() const
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);
if (compound == nullptr)
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)
auto r = chemComp.find(cif::Key("id") == compoundID);
if (r.empty())
{
chemComp.emplace({{"id", compoundID},
chemComp.emplace({
{"id", compoundID},
{"name", compound->name()},
{"formula", compound->formula()},
{"formula_weight", compound->formulaWeight()},
{"type", compound->type()}});
}
std::string entity_id;
if (isEntity)
{
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"];
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"},
{"pdbx_description", compound->name()},
{"formula_weight", compound->formulaWeight()}});
pdbxEntityNonpoly.emplace({{"entity_id", entityID},
pdbxEntityNonpoly.emplace({
{"entity_id", entity_id},
{"name", compound->name()},
{"comp_id", compoundID}});
}
}
return entity_id;
}
// // --------------------------------------------------------------------
......@@ -2340,7 +2353,7 @@ void Structure::changeResidue(const Residue &res, const std::string &newCompound
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)
{
......@@ -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;
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;
return insertCompound(comp_id, true);
}
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)
auto expected = R"(
data_TEST
loop_
_entity.id
_entity.type
_entity.src_method
_entity.pdbx_description
_entity.formula_weight
1 non-polymer syn 'PROTOPORPHYRIN IX CONTAINING FE' 616.487
loop_
_pdbx_entity_nonpoly.entity_id
_pdbx_entity_nonpoly.name
_pdbx_entity_nonpoly.comp_id
1 'PROTOPORPHYRIN IX CONTAINING FE' HEM
#
_chem_comp.id HEM
_chem_comp.type NON-POLYMER
_chem_comp.name 'PROTOPORPHYRIN IX CONTAINING FE'
_chem_comp.formula 'C34 H32 Fe N4 O4'
_chem_comp.formula_weight 616.487000
#
_pdbx_entity_nonpoly.entity_id 1
_pdbx_entity_nonpoly.name 'PROTOPORPHYRIN IX CONTAINING FE'
_pdbx_entity_nonpoly.comp_id HEM
#
_entity.id 1
_entity.type non-polymer
_entity.pdbx_description 'PROTOPORPHYRIN IX CONTAINING FE'
_entity.formula_weight 616.487000
#
)"_cf;
expected.loadDictionary("mmcif_pdbx_v50.dic");
......@@ -81,11 +85,7 @@ _pdbx_entity_nonpoly.comp_id
mmcif::Structure structure(file);
structure.createEntityNonPoly({
{ "src_method", "syn" },
{ "pdbx_description", "PROTOPORPHYRIN IX CONTAINING FE" },
{ "formula_weight", 616.487 }
}, "HEM" );
structure.createEntityNonPoly("HEM");
if (not (expected.firstDatablock() == structure.getFile().data()))
{
......@@ -94,38 +94,4 @@ _pdbx_entity_nonpoly.comp_id
<< 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
}
}
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(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