Skip to content

Commit

Permalink
chain renaming: update also MODRES
Browse files Browse the repository at this point in the history
refactor and unify renaming functions: change_ccd_code() was renamed to
rename_residues() and moved from polyheur.hpp to modify.hpp
  • Loading branch information
wojdyr committed May 13, 2024
1 parent 148f37b commit f60c2df
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 66 deletions.
52 changes: 43 additions & 9 deletions include/gemmi/modify.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,11 @@ inline void assign_serial_numbers(Structure& st, bool numbered_ter=false) {
}


/// Helper function for processing (usually: changing) names and numbers
/// in AtomAddress instances in metadata:
/// Connection, CisPep, Helix, Sheet::Strand.
/// Other fields are not updated here, in particular: ModRes, Entity::DbRef,
/// Entity::full_sequence, TlsGroup::Selection.
template<typename Func>
void process_addresses(Structure& st, Func func) {
for (Connection& con : st.connections) {
Expand All @@ -134,24 +139,53 @@ void process_addresses(Structure& st, Func func) {
}
}


inline void rename_chain(Structure& st, const std::string& old_name,
const std::string& new_name) {
process_addresses(st, [&](AtomAddress& aa) {
if (aa.chain_name == old_name)
aa.chain_name = new_name;
});
auto update = [&](std::string& name) {
if (name == old_name)
name = new_name;
};
process_addresses(st, [&](AtomAddress& aa) { update(aa.chain_name); });
for (ModRes& modres : st.mod_residues)
update(modres.chain_name);
for (RefinementInfo& ri : st.meta.refinement)
for (TlsGroup& tls : ri.tls_groups)
for (TlsGroup::Selection& sel : tls.selections)
if (sel.chain == old_name)
sel.chain = new_name;
update(sel.chain);
for (Model& model : st.models)
for (Chain& chain : model.chains)
update(chain.name);
}

inline void rename_residues(Structure& st, const std::string& old_name,
const std::string& new_name) {
auto update = [&](ResidueId& rid) {
if (rid.name == old_name)
rid.name = new_name;
};
process_addresses(st, [&](AtomAddress& aa) { update(aa.res_id); });
for (ModRes& modres : st.mod_residues)
update(modres.res_id);
for (Entity& ent : st.entities)
for (std::string& mon_ids : ent.full_sequence)
for (size_t start = 0;;) {
size_t end = mon_ids.find(',', start);
if (mon_ids.compare(start, end-start, old_name) == 0) {
mon_ids.replace(start, end-start, new_name);
if (end != std::string::npos)
end = start + new_name.size();
}
if (end == std::string::npos)
break;
start = end + 1;
}
for (Model& model : st.models)
for (Chain& chain : model.chains)
if (chain.name == old_name)
chain.name = new_name;
for (Residue& res : chain.residues)
update(res);
}


inline void rename_atom_names(Structure& st, const std::string& res_name,
const std::map<std::string, std::string>& old_new) {
auto update = [&old_new](std::string& name) {
Expand Down
10 changes: 1 addition & 9 deletions include/gemmi/polyheur.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -191,16 +191,8 @@ inline void trim_to_alanine(Chain& chain) {

// Functions for switching between long (>3 chars) residue names (CCD codes)
// and shortened ones that are compatible with the PDB format.
GEMMI_DLL
void change_ccd_code(Structure& st, const std::string& old, const std::string& new_);

GEMMI_DLL void shorten_ccd_codes(Structure& st);

inline void restore_full_ccd_codes(Structure& st) {
for (const auto& item : st.shortened_ccd_codes)
change_ccd_code(st, item.second, item.first);
st.shortened_ccd_codes.clear();
}
GEMMI_DLL void restore_full_ccd_codes(Structure& st);

} // namespace gemmi
#endif
2 changes: 1 addition & 1 deletion prog/convert.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -265,7 +265,7 @@ void convert(gemmi::Structure& st,
std::string new_name(sep+1);
if (options[Verbose])
std::cerr << "Renaming " << old_name << " to " << new_name << std::endl;
gemmi::change_ccd_code(st, old_name, new_name);
gemmi::rename_residues(st, old_name, new_name);
}

if (options[AssignRecords])
Expand Down
57 changes: 10 additions & 47 deletions src/polyheur.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#include <gemmi/polyheur.hpp>
#include <gemmi/resinfo.hpp> // for find_tabulated_residue
#include <gemmi/modify.hpp> // for rename_residues

namespace gemmi {

Expand Down Expand Up @@ -328,51 +329,6 @@ bool trim_to_alanine(Residue& res) {
return true;
}

void change_ccd_code(Structure& st, const std::string& old, const std::string& new_) {
auto process = [&](ResidueId& rid) {
if (rid.name == old)
rid.name = new_;
};
for (Model& model : st.models)
for (Chain& chain : model.chains)
for (Residue& res : chain.residues)
process(res);
for (Entity& ent : st.entities)
for (std::string& mon_ids : ent.full_sequence)
for (size_t start = 0;;) {
size_t end = mon_ids.find(',', start);
if (mon_ids.compare(start, end-start, old) == 0) {
mon_ids.replace(start, end-start, new_);
if (end != std::string::npos)
end = start + new_.size();
}
if (end == std::string::npos)
break;
start = end + 1;
}
for (Connection& conn : st.connections) {
process(conn.partner1.res_id);
process(conn.partner2.res_id);
}
for (CisPep& cispep : st.cispeps) {
process(cispep.partner_c.res_id);
process(cispep.partner_n.res_id);
}
for (ModRes& modres : st.mod_residues)
process(modres.res_id);
for (Helix& helix : st.helices) {
process(helix.start.res_id);
process(helix.end.res_id);
}
for (Sheet& sheet : st.sheets)
for (Sheet::Strand& strand : sheet.strands) {
process(strand.start.res_id);
process(strand.end.res_id);
process(strand.hbond_atom2.res_id);
process(strand.hbond_atom1.res_id);
}
}

template <size_t I, typename T1, typename T2>
bool in_vector_at(T1& x, std::vector<T2>& v) {
for (const auto& el : v)
Expand Down Expand Up @@ -410,7 +366,7 @@ void shorten_ccd_codes(Structure& st) {
if (!in_vector_at<1>(short_code, st.shortened_ccd_codes))
old_new.second = short_code;
}
// pick a new residue name and call change_ccd_code()
// pick a new residue name and call rename_residues()
int i = -1;
for (auto& old_new : st.shortened_ccd_codes) {
// If ~DE was not unique, use ~00, ~01, ...
Expand All @@ -421,8 +377,15 @@ void shorten_ccd_codes(Structure& st) {
if (!in_vector_at<1>(short_code, st.shortened_ccd_codes))
old_new.second = short_code;
}
change_ccd_code(st, old_new.first, old_new.second);
rename_residues(st, old_new.first, old_new.second);
}
}

void restore_full_ccd_codes(Structure& st) {
for (const auto& item : st.shortened_ccd_codes)
rename_residues(st, item.second, item.first);
st.shortened_ccd_codes.clear();
}


} // namespace gemmi

0 comments on commit f60c2df

Please sign in to comment.