Commit 35c99564 by Maarten L. Hekkelman

Fix importing sugars from PDB files

parent 1d8fe334
......@@ -525,12 +525,12 @@ class Sugar : public Residue
{
public:
Sugar(const Branch &branch, const std::string &compoundID,
const std::string &asymID, int authSeqID, int number);
const std::string &asymID, int authSeqID);
Sugar(Sugar &&rhs);
Sugar &operator=(Sugar &&rhs);
int num() const { return mNumber; }
int num() const { return std::stoi(mAuthSeqID); }
std::string name() const;
/// \brief Return the atom the C1 is linked to
......@@ -545,7 +545,6 @@ class Sugar : public Residue
private:
const Branch *mBranch;
int mNumber;
Atom mLink;
};
......
......@@ -1077,6 +1077,7 @@ class PDBFileParser
std::map<std::string, std::string> mBranch2EntityID;
std::map<std::string, std::string> mAsymID2EntityID;
std::map<std::string, std::string> mMod2parent;
std::set<std::string> mSugarEntities;
};
// --------------------------------------------------------------------
......@@ -3776,6 +3777,10 @@ void PDBFileParser::ConstructEntities()
for (auto &chain : mChains)
{
std::string asymID = cif::cifIdForNumber(asymNr++);
if (mMolID2EntityID.count(chain.mMolID) == 0)
continue;
std::string entityID = mMolID2EntityID[chain.mMolID];
mAsymID2EntityID[asymID] = entityID;
......@@ -4601,14 +4606,20 @@ void PDBFileParser::ConstructSugarTrees(int &asymNr)
}
}
mSugarEntities.insert(entityID);
// create an asym for this sugar tree
std::string asymID = cif::cifIdForNumber(asymNr++);
getCategory("struct_asym")->emplace({{"id", asymID},
{"pdbx_blank_PDB_chainid_flag", si->chainID == ' ' ? "Y" : "N"},
{"pdbx_modified", "N"},
{"entity_id", entityID}});
mAsymID2EntityID[asymID] = entityID;
getCategory("struct_asym")->emplace({
{"id", asymID},
{"pdbx_blank_PDB_chainid_flag", si->chainID == ' ' ? "Y" : "N"},
{"pdbx_modified", "N"},
{"entity_id", entityID}
});
std::string iCode{si->iCode};
ba::trim(iCode);
......@@ -5107,40 +5118,42 @@ void PDBFileParser::ParseConnectivtyAnnotation()
continue;
}
getCategory("struct_conn")->emplace({{"id", type + std::to_string(linkNr)},
{"conn_type_id", type},
// { "ccp4_link_id", ccp4LinkID },
{"ptnr1_label_asym_id", p1Asym},
{"ptnr1_label_comp_id", vS(18, 20)},
{"ptnr1_label_seq_id", (isResseq1 and p1Seq) ? std::to_string(p1Seq) : "."},
{"ptnr1_label_atom_id", vS(13, 16)},
{"pdbx_ptnr1_label_alt_id", vS(17, 17)},
{"pdbx_ptnr1_PDB_ins_code", vS(27, 27)},
{"pdbx_ptnr1_standard_comp_id", ""},
{"ptnr1_symmetry", sym1},
{"ptnr2_label_asym_id", p2Asym},
{"ptnr2_label_comp_id", vS(48, 50)},
{"ptnr2_label_seq_id", (isResseq2 and p2Seq) ? std::to_string(p2Seq) : "."},
{"ptnr2_label_atom_id", vS(43, 46)},
{"pdbx_ptnr2_label_alt_id", vS(47, 47)},
{"pdbx_ptnr2_PDB_ins_code", vS(57, 57)},
{"ptnr1_auth_asym_id", vS(22, 22)},
{"ptnr1_auth_comp_id", vS(18, 20)},
{"ptnr1_auth_seq_id", vI(23, 26)},
{"ptnr2_auth_asym_id", vS(52, 52)},
{"ptnr2_auth_comp_id", vS(48, 50)},
{"ptnr2_auth_seq_id", vI(53, 56)},
// { "ptnr1_auth_atom_id", vS(13, 16) },
// { "ptnr2_auth_atom_id", vS(43, 46) },
{"ptnr2_symmetry", sym2},
{"pdbx_dist_value", distance}});
getCategory("struct_conn")->emplace({
{"id", type + std::to_string(linkNr)},
{"conn_type_id", type},
// { "ccp4_link_id", ccp4LinkID },
{"ptnr1_label_asym_id", p1Asym},
{"ptnr1_label_comp_id", vS(18, 20)},
{"ptnr1_label_seq_id", (isResseq1 and p1Seq) ? std::to_string(p1Seq) : "."},
{"ptnr1_label_atom_id", vS(13, 16)},
{"pdbx_ptnr1_label_alt_id", vS(17, 17)},
{"pdbx_ptnr1_PDB_ins_code", vS(27, 27)},
{"pdbx_ptnr1_standard_comp_id", ""},
{"ptnr1_symmetry", sym1},
{"ptnr2_label_asym_id", p2Asym},
{"ptnr2_label_comp_id", vS(48, 50)},
{"ptnr2_label_seq_id", (isResseq2 and p2Seq) ? std::to_string(p2Seq) : "."},
{"ptnr2_label_atom_id", vS(43, 46)},
{"pdbx_ptnr2_label_alt_id", vS(47, 47)},
{"pdbx_ptnr2_PDB_ins_code", vS(57, 57)},
{"ptnr1_auth_asym_id", vS(22, 22)},
{"ptnr1_auth_comp_id", vS(18, 20)},
{"ptnr1_auth_seq_id", vI(23, 26)},
{"ptnr2_auth_asym_id", vS(52, 52)},
{"ptnr2_auth_comp_id", vS(48, 50)},
{"ptnr2_auth_seq_id", vI(53, 56)},
// { "ptnr1_auth_atom_id", vS(13, 16) },
// { "ptnr2_auth_atom_id", vS(43, 46) },
{"ptnr2_symmetry", sym2},
{"pdbx_dist_value", distance}
});
continue;
}
......@@ -5181,24 +5194,26 @@ void PDBFileParser::ParseConnectivtyAnnotation()
std::string iCode1str = iCode1 == ' ' ? std::string() : std::string{iCode1};
std::string iCode2str = iCode2 == ' ' ? std::string() : std::string{iCode2};
getCategory("struct_mon_prot_cis")->emplace({{"pdbx_id", serNum},
{"label_comp_id", pep1},
{"label_seq_id", lResSeq1},
{"label_asym_id", lAsym1},
{"label_alt_id", "."},
{"pdbx_PDB_ins_code", iCode1str},
{"auth_comp_id", pep1},
{"auth_seq_id", seqNum1},
{"auth_asym_id", std::string{chainID1}},
{"pdbx_label_comp_id_2", pep2},
{"pdbx_label_seq_id_2", lResSeq2},
{"pdbx_label_asym_id_2", lAsym2},
{"pdbx_PDB_ins_code_2", iCode2str},
{"pdbx_auth_comp_id_2", pep2},
{"pdbx_auth_seq_id_2", seqNum2},
{"pdbx_auth_asym_id_2", std::string{chainID2}},
{"pdbx_PDB_model_num", modNum},
{"pdbx_omega_angle", measure}});
getCategory("struct_mon_prot_cis")->emplace({
{"pdbx_id", serNum},
{"label_comp_id", pep1},
{"label_seq_id", lResSeq1},
{"label_asym_id", lAsym1},
{"label_alt_id", "."},
{"pdbx_PDB_ins_code", iCode1str},
{"auth_comp_id", pep1},
{"auth_seq_id", seqNum1},
{"auth_asym_id", std::string{chainID1}},
{"pdbx_label_comp_id_2", pep2},
{"pdbx_label_seq_id_2", lResSeq2},
{"pdbx_label_asym_id_2", lAsym2},
{"pdbx_PDB_ins_code_2", iCode2str},
{"pdbx_auth_comp_id_2", pep2},
{"pdbx_auth_seq_id_2", seqNum2},
{"pdbx_auth_asym_id_2", std::string{chainID2}},
{"pdbx_PDB_model_num", modNum},
{"pdbx_omega_angle", measure}
});
continue;
}
......@@ -5557,27 +5572,38 @@ void PDBFileParser::ParseCoordinate(int modelNr)
}
}
getCategory("atom_site")->emplace({{"group_PDB", groupPDB},
{"id", mAtomID},
{"type_symbol", element},
{"label_atom_id", name},
{"label_alt_id", altLoc != ' ' ? std::string{altLoc} : "."},
{"label_comp_id", resName},
{"label_asym_id", asymID},
{"label_entity_id", entityID},
{"label_seq_id", (isResseq and seqID > 0) ? std::to_string(seqID) : "."},
{"pdbx_PDB_ins_code", iCode == ' ' ? "" : std::string{iCode}},
{"Cartn_x", x},
{"Cartn_y", y},
{"Cartn_z", z},
{"occupancy", occupancy},
{"B_iso_or_equiv", tempFactor},
{"pdbx_formal_charge", charge},
{"auth_seq_id", resSeq},
{"auth_comp_id", resName},
{"auth_asym_id", std::string{chainID}},
{"auth_atom_id", name},
{"pdbx_PDB_model_num", modelNr}});
// if the atom is part of a sugar, we need to replace the auth_seq_id/resSeq
if (mSugarEntities.count(entityID))
{
using namespace cif::literals;
auto &branch_scheme = *getCategory("pdbx_branch_scheme");
resSeq = branch_scheme.find1<int>("asym_id"_key == asymID and "auth_seq_num"_key == resSeq, "pdb_seq_num");
}
getCategory("atom_site")->emplace({
{"group_PDB", groupPDB},
{"id", mAtomID},
{"type_symbol", element},
{"label_atom_id", name},
{"label_alt_id", altLoc != ' ' ? std::string{altLoc} : "."},
{"label_comp_id", resName},
{"label_asym_id", asymID},
{"label_entity_id", entityID},
{"label_seq_id", (isResseq and seqID > 0) ? std::to_string(seqID) : "."},
{"pdbx_PDB_ins_code", iCode == ' ' ? "" : std::string{iCode}},
{"Cartn_x", x},
{"Cartn_y", y},
{"Cartn_z", z},
{"occupancy", occupancy},
{"B_iso_or_equiv", tempFactor},
{"pdbx_formal_charge", charge},
{"auth_seq_id", resSeq},
{"auth_comp_id", resName},
{"auth_asym_id", std::string{chainID}},
{"auth_atom_id", name},
{"pdbx_PDB_model_num", modelNr}
});
InsertAtomType(element);
......
......@@ -1123,17 +1123,15 @@ int Polymer::Distance(const Monomer &a, const Monomer &b) const
// --------------------------------------------------------------------
Sugar::Sugar(const Branch &branch, const std::string &compoundID,
const std::string &asymID, int authSeqID, int number)
const std::string &asymID, int authSeqID)
: Residue(branch.structure(), compoundID, asymID, 0, std::to_string(authSeqID))
, mBranch(&branch)
, mNumber(number)
{
}
Sugar::Sugar(Sugar &&rhs)
: Residue(std::forward<Residue>(rhs))
, mBranch(rhs.mBranch)
, mNumber(rhs.mNumber)
{
}
......@@ -1144,7 +1142,6 @@ Sugar &Sugar::operator=(Sugar &&rhs)
{
Residue::operator=(std::forward<Residue>(rhs));
mBranch = rhs.mBranch;
mNumber = rhs.mNumber;
}
return *this;
......@@ -1206,10 +1203,10 @@ Branch::Branch(Structure &structure, const std::string &asymID)
for (const auto &[entity_id] : struct_asym.find<std::string>("id"_key == asymID, "entity_id"))
{
for (const auto &[comp_id, number, auth_seq_num] : branch_scheme.find<std::string, int, int>(
"asym_id"_key == asymID, "mon_id", "pdb_seq_num", "auth_seq_num"))
for (const auto &[comp_id, num] : branch_scheme.find<std::string, int>(
"asym_id"_key == asymID, "mon_id", "pdb_seq_num"))
{
emplace_back(*this, comp_id, asymID, auth_seq_num, number);
emplace_back(*this, comp_id, asymID, num);
}
for (const auto &[num1, num2, atom1, atom2] : branch_link.find<size_t, size_t, std::string, std::string>(
......@@ -2260,11 +2257,13 @@ std::string Structure::createNonpoly(const std::string &entity_id, const std::ve
auto &struct_asym = db["struct_asym"];
std::string asym_id = struct_asym.getUniqueID();
struct_asym.emplace({{"id", asym_id},
struct_asym.emplace({
{"id", asym_id},
{"pdbx_blank_PDB_chainid_flag", "N"},
{"pdbx_modified", "N"},
{"entity_id", entity_id},
{"details", "?"}});
{"details", "?"}
});
std::string comp_id = db["pdbx_entity_nonpoly"].find1<std::string>("entity_id"_key == entity_id, "comp_id");
......@@ -2276,7 +2275,8 @@ std::string Structure::createNonpoly(const std::string &entity_id, const std::ve
{
auto atom_id = atom_site.getUniqueID("");
auto &&[row, inserted] = atom_site.emplace({{"group_PDB", atom.get_property<std::string>("group_PDB")},
auto &&[row, inserted] = atom_site.emplace({
{"group_PDB", atom.get_property<std::string>("group_PDB")},
{"id", atom_id},
{"type_symbol", atom.get_property<std::string>("type_symbol")},
{"label_atom_id", atom.get_property<std::string>("label_atom_id")},
......@@ -2296,7 +2296,8 @@ std::string Structure::createNonpoly(const std::string &entity_id, const std::ve
{"auth_comp_id", comp_id},
{"auth_asym_id", asym_id},
{"auth_atom_id", atom.get_property<std::string>("label_atom_id")},
{"pdbx_PDB_model_num", 1}});
{"pdbx_PDB_model_num", 1}
});
auto &newAtom = emplace_atom(std::make_shared<Atom::AtomImpl>(db, atom_id, row));
res.addAtom(newAtom);
......@@ -2328,11 +2329,13 @@ std::string Structure::createNonpoly(const std::string &entity_id, std::vector<s
auto &struct_asym = db["struct_asym"];
std::string asym_id = struct_asym.getUniqueID();
struct_asym.emplace({{"id", asym_id},
struct_asym.emplace({
{"id", asym_id},
{"pdbx_blank_PDB_chainid_flag", "N"},
{"pdbx_modified", "N"},
{"entity_id", entity_id},
{"details", "?"}});
{"details", "?"}
});
std::string comp_id = db["pdbx_entity_nonpoly"].find1<std::string>("entity_id"_key == entity_id, "comp_id");
......@@ -2406,7 +2409,7 @@ Branch &Structure::createBranch(std::vector<std::vector<cif::Item>> &nag_atoms)
std::string asym_id = struct_asym.getUniqueID();
auto &branch = mBranches.emplace_back(*this, asym_id);
auto &sugar = branch.emplace_back(branch, "NAG", asym_id, 1, 1);
auto &sugar = branch.emplace_back(branch, "NAG", asym_id, 1);
auto tmp_entity_id = db["entity"].getUniqueID("");
auto &atom_site = db["atom_site"];
......@@ -2520,7 +2523,7 @@ Branch &Structure::extendBranch(const std::string &asym_id, std::vector<std::vec
int sugarNum = branch.size() + 1;
auto &sugar = branch.emplace_back(branch, compoundID, asym_id, sugarNum, sugarNum);
auto &sugar = branch.emplace_back(branch, compoundID, asym_id, sugarNum);
for (auto &atom : atom_info)
{
......
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