NCBI C++ ToolKit
molecule.cpp
Go to the documentation of this file.

Go to the SVN repository for this file.

1 /* $Id: molecule.cpp 97253 2022-06-29 17:35:29Z dzhang $
2 * ===========================================================================
3 *
4 * PUBLIC DOMAIN NOTICE
5 * National Center for Biotechnology Information
6 *
7 * This software/database is a "United States Government Work" under the
8 * terms of the United States Copyright Act. It was written as part of
9 * the author's official duties as a United States Government employee and
10 * thus cannot be copyrighted. This software/database is freely available
11 * to the public for use. The National Library of Medicine and the U.S.
12 * Government have not placed any restriction on its use or reproduction.
13 *
14 * Although all reasonable efforts have been taken to ensure the accuracy
15 * and reliability of the software and data, the NLM and the U.S.
16 * Government do not and cannot warrant the performance or results that
17 * may be obtained by using this software or data. The NLM and the U.S.
18 * Government disclaim all warranties, express or implied, including
19 * warranties of performance, merchantability or fitness for any particular
20 * purpose.
21 *
22 * Please cite the author in any work or product based on this material.
23 *
24 * ===========================================================================
25 *
26 * Authors: Paul Thiessen
27 *
28 * File Description:
29 * Classes to hold molecules
30 *
31 * ===========================================================================
32 */
33 
34 #include <ncbi_pch.hpp>
35 #include <corelib/ncbistd.hpp>
36 
44 
46 
47 #include "molecule.hpp"
48 #include "residue.hpp"
49 #include "bond.hpp"
50 #include "style_manager.hpp"
51 #include "structure_set.hpp"
52 #include "coord_set.hpp"
53 #include "atom_set.hpp"
54 #include "chemical_graph.hpp"
55 #include "molecule_identifier.hpp"
56 #include "show_hide_manager.hpp"
57 #include "cn3d_tools.hpp"
58 #include "opengl_renderer.hpp"
59 #include "cn3d_colors.hpp"
60 
63 
64 
65 BEGIN_SCOPE(Cn3D)
66 
67 const int Molecule::NO_DOMAIN_SET = -1;
68 
70  const CMolecule_graph& graph,
72  const ResidueGraphList& localDictionary) :
73  StructureBase(parentGraph), type(eOther), nDomains(0), sequence(NULL)
74 {
75  // get ID, name, and type
76  id = graph.GetId().Get();
77  CMolecule_graph::TDescr::const_iterator k, ke=graph.GetDescr().end();
78  for (k=graph.GetDescr().begin(); k!=ke; ++k) {
79  if (k->GetObject().IsMolecule_type()) {
80  type = static_cast<eType>(k->GetObject().GetMolecule_type());
81  }
82  if (k->GetObject().IsName()) {
83  name = k->GetObject().GetName();
84  }
85  }
86 
87  // get Seq-id for biopolymer chains (for sequence alignment stuff)
89  if (IsProtein() || IsNucleotide()) {
90  if (graph.IsSetSeq_id()) {
91  seqIDs.push_back(CRef<CSeq_id>(const_cast<CSeq_id*>(&(graph.GetSeq_id()))));
92  } else {
93  ERRORMSG("Molecule::Molecule() - biopolymer molecule, but can't get Seq-id");
94  return;
95  }
96  }
97 
98  const StructureObject *object;
99  if (!GetParentOfType(&object)) return;
100 
101  // load residues from SEQUENCE OF Residue, storing virtual bonds along the way
102  CMolecule_graph::TInter_residue_bonds::const_iterator j, je, jOrig;
103  if (graph.IsSetInter_residue_bonds()) {
104  j = graph.GetInter_residue_bonds().begin();
105  je = graph.GetInter_residue_bonds().end();
106  }
107  const Residue *prevResidue = NULL;
108  const Bond *prevBond = NULL;
109  CMolecule_graph::TResidue_sequence::const_iterator i, ie=graph.GetResidue_sequence().end();
110  int nResidues = 0;
111 
112  for (i=graph.GetResidue_sequence().begin(); i!=ie; ++i) {
113 
114  const Residue *residue = new Residue(this, (*i).GetObject(), id,
115  standardDictionary, localDictionary, graph.GetResidue_sequence().size(), type);
116  residues[residue->id] = residue;
117  ++nResidues;
118 
119  // this assumption is frequently made elsewhere, relating seqLocs (numbering from zero)
120  // to residue ID's (numbering from one) - so enforce it here
121  if (residue->id != nResidues)
122  ERRORMSG("Residue ID's must be ordered consecutively starting with one");
123 
124  // virtual bonds between successive alphas
125  if (prevResidue && prevResidue->alphaID != Residue::NO_ALPHA_ID &&
126  residue->alphaID != Residue::NO_ALPHA_ID) {
127 
128  bool foundReal = false;
129 
130  // see if there's a "real" inter-residue bond between these in the chemical graph
131  if (graph.IsSetInter_residue_bonds()) {
132  jOrig = j;
133  do {
134  if ((j->GetObject().GetAtom_id_1().GetResidue_id().Get() == prevResidue->id &&
135  j->GetObject().GetAtom_id_2().GetResidue_id().Get() == residue->id) ||
136  (j->GetObject().GetAtom_id_2().GetResidue_id().Get() == prevResidue->id &&
137  j->GetObject().GetAtom_id_1().GetResidue_id().Get() == residue->id))
138  foundReal = true;
139  if (++j == je) j = graph.GetInter_residue_bonds().begin();
140  } while (!foundReal && j != jOrig);
141  }
142 
143  // for alpha only models, there are no inter-residue bonds in the
144  // chemical graph, so check inter-atomic distances for cases where either one
145  // of the two residues is alpha only.
146  if (!foundReal && (IsProtein() || IsNucleotide()) &&
147  (residue->NAtomsWithAnyCoords() == 1 || prevResidue->NAtomsWithAnyCoords() == 1)) {
148 
149  // get atom coordinates
150  AtomPntr ap1(id, residue->id, residue->alphaID);
151  const AtomCoord* atom1 = object->coordSets.front()->atomSet->GetAtom(ap1, true, true);
152  AtomPntr ap2(id, prevResidue->id, prevResidue->alphaID);
153  const AtomCoord* atom2 = object->coordSets.front()->atomSet->GetAtom(ap2, true, true);
154 
155  // check distance - ok if <= 5.0 Angstroms (or 10.0 for nucleotides)
156  if (atom1 && atom2 &&
157  (atom1->site - atom2->site).length() <=
158  (IsProtein() ? 5.0 : 10.0))
159  foundReal = true;
160  }
161 
162  if (foundReal) {
163  const Bond *bond = MakeBond(this,
164  id, prevResidue->id, prevResidue->alphaID,
165  id, residue->id, residue->alphaID,
167  if (bond) {
168  interResidueBonds.push_back(bond);
169  if (prevBond) {
170  (const_cast<Bond *>(prevBond))->nextVirtual = bond;
171  (const_cast<Bond *>(bond))->previousVirtual = prevBond;
172  }
173  }
174  prevBond = bond;
175  } else
176  prevBond = NULL;
177  } else
178  prevBond = NULL;
179 
180  prevResidue = residue;
181  }
182 
183  residueDomains.resize(residues.size(), NO_DOMAIN_SET);
184 
185  // keep s.s. maps only for protein chains
186  if (IsProtein()) residueSecondaryStructures.resize(residues.size(), eCoil);
187 
188  // load inter-residue bonds from SEQUENCE OF Inter-residue-bond OPTIONAL
189  if (graph.IsSetInter_residue_bonds()) {
190  je = graph.GetInter_residue_bonds().end();
191  for (j=graph.GetInter_residue_bonds().begin(); j!=je; ++j) {
192 
193  int order = j->GetObject().IsSetBond_order() ?
194  j->GetObject().GetBond_order() : Bond::eUnknown;
195  const Bond *bond = MakeBond(this,
196  j->GetObject().GetAtom_id_1(),
197  j->GetObject().GetAtom_id_2(),
198  order);
199  if (bond) interResidueBonds.push_back(bond);
200 
201  // add to disulfide map if virtual disulfide added or this bond is flagged as disulfide
202  if (parentGraph->CheckForDisulfide(this,
203  j->GetObject().GetAtom_id_1(), j->GetObject().GetAtom_id_2(),
204  &interResidueBonds, const_cast<Bond*>(bond), this) ||
205  (bond && bond->order == Bond::eRealDisulfide)) {
206  disulfideMap[j->GetObject().GetAtom_id_1().GetResidue_id().Get()] =
207  j->GetObject().GetAtom_id_2().GetResidue_id().Get();
208  disulfideMap[j->GetObject().GetAtom_id_2().GetResidue_id().Get()] =
209  j->GetObject().GetAtom_id_1().GetResidue_id().Get();
210  }
211  }
212  }
213 
214  // get identifier
216 }
217 
218 Vector Molecule::GetResidueColor(int sequenceIndex) const
219 {
220  static const Vector gray(.5,.5,.5);
221 
222  // this assumes that the "index" - the position of the residue in the sequence,
223  // starting from zero, is always one less than the residueID from the ASN1
224  // data, which starts from one.
225  ResidueMap::const_iterator r = residues.find(sequenceIndex + 1);
226 
227  if (r == residues.end()) return gray;
228  const Residue *residue = r->second;
229 
230  // if no known alpha atom, just use gray
231  if (residue->alphaID == Residue::NO_ALPHA_ID) return gray;
232  AtomPntr atom(id, residue->id, residue->alphaID);
233 
234  // just use the first AtomSet (e.g. first model) of this object
235  const StructureObject *object;
236  if (!GetParentOfType(&object)) return gray;
237  const AtomCoord *atomCoord = object->coordSets.front()->atomSet->
238  GetAtom(atom, parentSet->showHideManager->OverlayConfEnsembles(), true);
239  if (!atomCoord) return gray;
240 
241  AtomStyle style;
242  if (!parentSet->styleManager->GetAtomStyle(residue, atom, atomCoord, &style)) return gray;
243  return style.color;
244 }
245 
246 int Molecule::GetAlphaCoords(int nResidues, const int *seqIndexes, const Vector * *coords) const
247 {
248  const StructureObject *object;
249  if (!GetParentOfType(&object)) return false;
250  if (object->coordSets.size() != 1) {
251  ERRORMSG("Can't align structures with multiple CoordSets");
252  return -1;
253  }
254 
255  int nCoords = 0;
256  for (int i=0; i<nResidues; ++i) {
257 
258  coords[i] = NULL;
259 
260  if (seqIndexes[i] < 0)
261  continue;
262  int rID = seqIndexes[i] + 1; // residueIDs start at 1
263 
264  ResidueMap::const_iterator r = residues.find(rID);
265  if (r == residues.end()) {
266  ERRORMSG("Can't find residueID " << rID
267  << " in " << identifier->pdbID << " chain '"
268  << identifier->pdbChain << "'");
269 
270  return -1;
271  }
272 
273  int aID = (r->second->alphaID);
274  if (aID == Residue::NO_ALPHA_ID) {
275  WARNINGMSG("No alpha atom in residueID " << rID
276  << " from " << identifier->pdbID << " chain '"
277  << identifier->pdbChain << "'");
278 
279  continue;
280  }
281 
282  AtomPntr atom(id, rID, aID);
283  const AtomCoord* atomCoord = object->coordSets.front()->atomSet->GetAtom(atom);
284  if (!atomCoord) {
285  WARNINGMSG("Can't get AtomCoord for (m"
286  << id << ",r" << rID << ",a" << aID << ")");
287  continue;
288  }
289 
290  coords[i] = &(atomCoord->site);
291  ++nCoords;
292  }
293 
294  return nCoords;
295 }
296 
297 bool Molecule::DrawAllWithTerminiLabels(const AtomSet *atomSet) const
298 {
299  // draw regular objects
300  if (!DrawAll(atomSet)) return false;
301 
302  // add termini labels
303  if ((IsProtein() || IsNucleotide()) && NResidues() >= 2 && parentSet->showHideManager->IsVisible(this)) {
304 
305  const StyleSettings& settings = parentSet->styleManager->GetGlobalStyle();
306  if ((IsProtein() && settings.proteinLabels.terminiOn) ||
307  (IsNucleotide() && settings.nucleotideLabels.terminiOn)) {
308 
309  // try to color labels to contrast with background
310  static const Vector white(1,1,1), black(0,0,0);
311  const Vector& labelColor =
312  Colors::IsLightColor(settings.backgroundColor) ? black : white;
313 
314  // do start (N or 5') and end (C or 3') labels
315  for (int startTerminus=1; startTerminus>=0; --startTerminus) {
316 
317  // determine color and location - assumes sequential residue id's (from 1)
318  const Vector *alphaPos = NULL, *prevPos = NULL;
319  int res = startTerminus ? 1 : residues.size(),
320  resEnd = startTerminus ? residues.size() : 1,
321  resInc = startTerminus ? 1 : -1;
322 
323  // find coordinates of two terminal alpha atoms
324  const Residue *termRes = NULL;
325  for (; res!=resEnd; res+=resInc) {
326  const Residue *residue = residues.find(res)->second;
327  if (residue->alphaID != Residue::NO_ALPHA_ID) {
328  AtomPntr ap(id, res, residue->alphaID);
329  const AtomCoord *atom =
330  atomSet->GetAtom(ap, parentSet->showHideManager->OverlayConfEnsembles(), true);
331  if (atom) {
332  if (!alphaPos) {
333  alphaPos = &(atom->site);
334  termRes = residue;
335  } else if (!prevPos) {
336  prevPos = &(atom->site);
337  break;
338  }
339  }
340  }
341  }
342  if (!(alphaPos && prevPos)) {
343  WARNINGMSG("Molecule::DrawAllWithTerminiLabels() - "
344  << "can't get two terminal alpha coords");
345  continue;
346  }
347  if (!parentSet->showHideManager->IsVisible(termRes)) continue;
348  Vector labelPosition = *alphaPos + 0.5 * (*alphaPos - *prevPos);
349 
350  // determine label text
351  CNcbiOstrstream oss;
352  if (IsProtein()) {
353  if (startTerminus)
354  oss << "N";
355  else
356  oss << "C";
357  } else {
358  if (startTerminus)
359  oss << "5'";
360  else
361  oss << "3'";
362  }
363 
364  if (!identifier->pdbChain.empty() && identifier->pdbChain != " ")
365  oss << " (" << identifier->pdbChain << ')';
366 
367  // draw label
368  string labelText = (string) CNcbiOstrstreamToString(oss);
369  parentSet->renderer->DrawLabel(labelText, labelPosition, labelColor);
370  }
371  }
372  }
373 
374  return true;
375 }
376 
377 END_SCOPE(Cn3D)
User-defined methods of the data storage class.
User-defined methods of the data storage class.
User-defined methods of the data storage class.
User-defined methods of the data storage class.
const Bond * MakeBond(StructureBase *parent, int mID1, int rID1, int aID1, int mID2, int rID2, int aID2, int bondOrder)
Definition: bond.cpp:65
static const CBiostruc_residue_graph_set * standardDictionary
Vector site
Definition: atom_set.hpp:62
const AtomCoord * GetAtom(const AtomPntr &atom, bool getAny=false, bool suppressWarning=false) const
Definition: atom_set.cpp:252
Definition: bond.hpp:50
@ eUnknown
Definition: bond.hpp:59
@ eRealDisulfide
Definition: bond.hpp:61
@ eVirtual
Definition: bond.hpp:60
eBondOrder order
Definition: bond.hpp:69
const Bond * previousVirtual
Definition: bond.hpp:70
CMolecule_graph –.
CNcbiOstrstreamToString class helps convert CNcbiOstrstream to a string Sample usage:
Definition: ncbistre.hpp:802
bool CheckForDisulfide(const Molecule *molecule, const ncbi::objects::CAtom_pntr &atomPtr1, const ncbi::objects::CAtom_pntr &atomPtr2, std::list< const Bond * > *bondList, Bond *bond, StructureBase *parent)
static bool IsLightColor(const Vector &color)
std::list< ncbi::CRef< ncbi::objects::CSeq_id > > SeqIdList
static const MoleculeIdentifier * GetIdentifier(const Molecule *molecule, const SeqIdList &ids)
std::vector< int > residueDomains
Definition: molecule.hpp:105
std::string name
Definition: molecule.hpp:85
int GetAlphaCoords(int nResidues, const int *seqIndexes, const Vector **coords) const
Definition: molecule.cpp:246
DisulfideMap disulfideMap
Definition: molecule.hpp:95
bool IsNucleotide(void) const
Definition: molecule.hpp:116
Vector GetResidueColor(int sequenceIndex) const
Definition: molecule.cpp:218
std::vector< eSecStruc > residueSecondaryStructures
Definition: molecule.hpp:104
static const int NO_DOMAIN_SET
Definition: molecule.hpp:98
const MoleculeIdentifier * identifier
Definition: molecule.hpp:86
bool DrawAllWithTerminiLabels(const AtomSet *atomSet=NULL) const
Definition: molecule.cpp:297
BondList interResidueBonds
Definition: molecule.hpp:91
Molecule(ChemicalGraph *parentGraph, const ncbi::objects::CMolecule_graph &graph, const ResidueGraphList &standardDictionary, const ResidueGraphList &localDictionary)
Definition: molecule.cpp:69
bool IsProtein(void) const
Definition: molecule.hpp:115
unsigned int NResidues(void) const
Definition: molecule.hpp:121
ResidueMap residues
Definition: molecule.hpp:89
void DrawLabel(const std::string &text, const Vector &center, const Vector &color)
int id
Definition: residue.hpp:69
int NAtomsWithAnyCoords(void) const
Definition: residue.hpp:125
static const int NO_ALPHA_ID
Definition: residue.hpp:75
int alphaID
Definition: residue.hpp:76
bool OverlayConfEnsembles(void) const
bool IsVisible(const StructureBase *entity) const
virtual bool DrawAll(const AtomSet *atomSet=NULL) const
StructureSet * parentSet
bool GetParentOfType(const T **ptr, bool warnIfNotFound=true) const
CoordSetList coordSets
ShowHideManager * showHideManager
OpenGLRenderer * renderer
StyleManager * styleManager
const StyleSettings & GetGlobalStyle(void) const
bool GetAtomStyle(const Residue *residue, const AtomPntr &atom, const AtomCoord *coord, AtomStyle *atomStyle, const StyleSettings::BackboneStyle **saveBackboneStyle=NULL, const StyleSettings::GeneralStyle **saveGeneralStyle=NULL) const
LabelStyle nucleotideLabels
Vector backgroundColor
LabelStyle proteinLabels
#define WARNINGMSG(stream)
Definition: cn3d_tools.hpp:85
#define ERRORMSG(stream)
Definition: cn3d_tools.hpp:86
Include a standard set of the NCBI C++ Toolkit most basic headers.
#define NULL
Definition: ncbistd.hpp:225
const TPrim & Get(void) const
Definition: serialbase.hpp:347
#define END_SCOPE(ns)
End the previously defined scope.
Definition: ncbistl.hpp:75
#define BEGIN_SCOPE(ns)
Define a new scope.
Definition: ncbistl.hpp:72
bool IsSetInter_residue_bonds(void) const
Check if a value has been assigned to Inter_residue_bonds data member.
const TDescr & GetDescr(void) const
Get the Descr member data.
const TSeq_id & GetSeq_id(void) const
Get the Seq_id member data.
const TInter_residue_bonds & GetInter_residue_bonds(void) const
Get the Inter_residue_bonds member data.
const TId & GetId(void) const
Get the Id member data.
bool IsSetSeq_id(void) const
Check if a value has been assigned to Seq_id data member.
const TResidue_sequence & GetResidue_sequence(void) const
Get the Residue_sequence member data.
@ eOther
Something else.
Definition: unicode.hpp:59
int i
USING_SCOPE(objects)
USING_NCBI_SCOPE
Definition: molecule.cpp:61
std::list< ncbi::CRef< ncbi::objects::CResidue_graph > > ResidueGraphList
Definition: molecule.hpp:58
double r(size_t dimension_, const Int4 *score_, const double *prob_, double theta_)
Definition: type.c:6
Modified on Tue May 28 05:51:22 2024 by modify_doxy.py rev. 669887