chemical_graph.cpp
上传用户:yhdzpy8989
上传日期:2007-06-13
资源大小:13604k
文件大小:27k
源码类别:

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: chemical_graph.cpp,v $
  4.  * PRODUCTION Revision 1000.2  2004/06/01 18:28:03  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.40
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /*  $Id: chemical_graph.cpp,v 1000.2 2004/06/01 18:28:03 gouriano Exp $
  10. * ===========================================================================
  11. *
  12. *                            PUBLIC DOMAIN NOTICE
  13. *               National Center for Biotechnology Information
  14. *
  15. *  This software/database is a "United States Government Work" under the
  16. *  terms of the United States Copyright Act.  It was written as part of
  17. *  the author's official duties as a United States Government employee and
  18. *  thus cannot be copyrighted.  This software/database is freely available
  19. *  to the public for use. The National Library of Medicine and the U.S.
  20. *  Government have not placed any restriction on its use or reproduction.
  21. *
  22. *  Although all reasonable efforts have been taken to ensure the accuracy
  23. *  and reliability of the software and data, the NLM and the U.S.
  24. *  Government do not and cannot warrant the performance or results that
  25. *  may be obtained by using this software or data. The NLM and the U.S.
  26. *  Government disclaim all warranties, express or implied, including
  27. *  warranties of performance, merchantability or fitness for any particular
  28. *  purpose.
  29. *
  30. *  Please cite the author in any work or product based on this material.
  31. *
  32. * ===========================================================================
  33. *
  34. * Authors:  Paul Thiessen
  35. *
  36. * File Description:
  37. *      Classes to hold the graph of chemical bonds
  38. *
  39. * ===========================================================================
  40. */
  41. #ifdef _MSC_VER
  42. #pragma warning(disable:4018)   // disable signed/unsigned mismatch warning in MSVC
  43. #endif
  44. #include <ncbi_pch.hpp>
  45. #include <corelib/ncbistd.hpp>
  46. #include <objects/mmdb1/Biostruc_residue_graph_set.hpp>
  47. #include <objects/mmdb1/Biostruc_id.hpp>
  48. #include <objects/general/Dbtag.hpp>
  49. #include <objects/mmdb3/Biostruc_feature_set_descr.hpp>
  50. #include <objects/mmdb3/Biostruc_feature.hpp>
  51. #include <objects/mmdb3/Chem_graph_pntrs.hpp>
  52. #include <objects/mmdb3/Residue_pntrs.hpp>
  53. #include <objects/mmdb3/Residue_interval_pntr.hpp>
  54. #include <objects/mmdb3/Biostruc_feature_id.hpp>
  55. #include <objects/mmdb1/Molecule_id.hpp>
  56. #include <objects/mmdb1/Residue_id.hpp>
  57. #include <objects/mmdb1/Atom_id.hpp>
  58. #include <objects/general/Object_id.hpp>
  59. #include "chemical_graph.hpp"
  60. #include "asn_reader.hpp"
  61. #include "molecule.hpp"
  62. #include "bond.hpp"
  63. #include "structure_set.hpp"
  64. #include "opengl_renderer.hpp"
  65. #include "coord_set.hpp"
  66. #include "atom_set.hpp"
  67. #include "object_3d.hpp"
  68. #include "cn3d_tools.hpp"
  69. #include "molecule_identifier.hpp"
  70. USING_NCBI_SCOPE;
  71. USING_SCOPE(objects);
  72. BEGIN_SCOPE(Cn3D)
  73. static const CBiostruc_residue_graph_set* standardDictionary = NULL;
  74. void LoadStandardDictionary(const char *filename)
  75. {
  76.     standardDictionary = new CBiostruc_residue_graph_set;
  77.     // read dictionary file
  78.     string err;
  79.     if (!ReadASNFromFile(filename,
  80.             const_cast<CBiostruc_residue_graph_set*>(standardDictionary), true, &err))
  81.         FATALMSG("Error reading standard residue dictionary: " << err);
  82.     // make sure it's the right thing
  83.     if (!standardDictionary->IsSetId() ||
  84.         !standardDictionary->GetId().front().GetObject().IsOther_database() ||
  85.         standardDictionary->GetId().front().GetObject().GetOther_database().GetDb() != "Standard residue dictionary" ||
  86.         !standardDictionary->GetId().front().GetObject().GetOther_database().GetTag().IsId() ||
  87.         standardDictionary->GetId().front().GetObject().GetOther_database().GetTag().GetId() != 1)
  88.         FATALMSG("file '" << filename << "' does not contain expected dictionary data");
  89. }
  90. void DeleteStandardDictionary(void)
  91. {
  92.     if (standardDictionary) {
  93.         delete standardDictionary;
  94.         standardDictionary = NULL;
  95.     }
  96. }
  97. ChemicalGraph::ChemicalGraph(StructureBase *parent, const CBiostruc_graph& graph,
  98.     const FeatureList& features) :
  99.     StructureBase(parent), displayListOtherStart(OpenGLRenderer::NO_LIST)
  100. {
  101.     if (!standardDictionary) {
  102.         FATALMSG("need to load standard dictionary first");
  103.         return;
  104.     }
  105.     // figure out what models we'll be drawing, based on contents of parent
  106.     // StructureSet and StructureObject
  107.     const StructureObject *object;
  108.     if (!GetParentOfType(&object)) return;
  109.     // if this is the only StructureObject in this StructureSet, and if this
  110.     // StructureObject has only one CoordSet, and if this CoordSet's AtomSet
  111.     // has multiple ensembles, then use multiple altConf ensemble
  112.     int nAlts = 0;
  113.     if (!parentSet->IsMultiStructure() && object->coordSets.size() == 1 &&
  114.         object->coordSets.front()->atomSet->ensembles.size() > 1) {
  115.         AtomSet *atomSet = object->coordSets.front()->atomSet;
  116.         AtomSet::EnsembleList::iterator e, ee=atomSet->ensembles.end();
  117.         for (e=atomSet->ensembles.begin(); e!=ee; ++e) {
  118.             atomSetList.push_back(make_pair(atomSet, *e));
  119.             ++nAlts;
  120.         }
  121.     // otherwise, use all CoordSets using default altConf ensemble for single
  122.     // structure; for multiple structure StructureSet, use only first CoordSet
  123.     } else {
  124.         StructureObject::CoordSetList::const_iterator c, ce=object->coordSets.end();
  125.         for (c=object->coordSets.begin(); c!=ce; ++c) {
  126.             atomSetList.push_back(make_pair((*c)->atomSet,
  127.                 reinterpret_cast<const string *>(NULL)));   // VC++ requires this cast for some reason...
  128.             ++nAlts;
  129.             if (parentSet->IsMultiStructure()) break;
  130.         }
  131.     }
  132.     TRACEMSG("nAlts = " << nAlts);
  133.     if (!nAlts) {
  134.         WARNINGMSG("ChemicalGraph has zero AtomSets!");
  135.         return;
  136.     }
  137.     unsigned int firstNewFrame = parentSet->frameMap.size();
  138.     parentSet->frameMap.resize(firstNewFrame + nAlts);
  139.     // load molecules from SEQUENCE OF Molecule-graph
  140.     CBiostruc_graph::TMolecule_graphs::const_iterator i, ie=graph.GetMolecule_graphs().end();
  141.     for (i=graph.GetMolecule_graphs().begin(); i!=ie; ++i) {
  142.         Molecule *molecule = new Molecule(this,
  143.             i->GetObject(),
  144.             standardDictionary->GetResidue_graphs(),
  145.             graph.GetResidue_graphs());
  146.         if (molecules.find(molecule->id) != molecules.end())
  147.             ERRORMSG("confused by repeated Molecule-graph ID's");
  148.         molecules[molecule->id] = molecule;
  149.         // set molecules' display list; each protein or nucleotide molecule
  150.         // gets its own display list (one display list for each molecule for
  151.         // each set of coordinates), while everything else - hets, solvents,
  152.         // inter-molecule bonds - goes in a single list.
  153.         for (int n=0; n<nAlts; ++n) {
  154.             if (molecule->IsProtein() || molecule->IsNucleotide()) {
  155.                 molecule->displayLists.push_back(++(parentSet->lastDisplayList));
  156.                 parentSet->frameMap[firstNewFrame + n].push_back(parentSet->lastDisplayList);
  157.                 parentSet->transformMap[parentSet->lastDisplayList] = &(object->transformToMaster);
  158.             } else { // het/solvent
  159.                 if (displayListOtherStart == OpenGLRenderer::NO_LIST) {
  160.                     displayListOtherStart = parentSet->lastDisplayList + 1;
  161.                     parentSet->lastDisplayList += nAlts;
  162.                 }
  163.                 molecule->displayLists.push_back(displayListOtherStart + n);
  164.             }
  165.         }
  166.     }
  167.     // load connections from SEQUENCE OF Inter-residue-bond OPTIONAL
  168.     if (graph.IsSetInter_molecule_bonds()) {
  169.         CBiostruc_graph::TInter_molecule_bonds::const_iterator j, je=graph.GetInter_molecule_bonds().end();
  170.         for (j=graph.GetInter_molecule_bonds().begin(); j!=je; ++j) {
  171.             int order = j->GetObject().IsSetBond_order() ?
  172.                 j->GetObject().GetBond_order() : Bond::eUnknown;
  173.             const Bond *bond = MakeBond(this,
  174.                 j->GetObject().GetAtom_id_1(),
  175.                 j->GetObject().GetAtom_id_2(),
  176.                 order);
  177.             if (bond) interMoleculeBonds.push_back(bond);
  178.             if (CheckForDisulfide(NULL,
  179.                     j->GetObject().GetAtom_id_1(), j->GetObject().GetAtom_id_2(),
  180.                     &interMoleculeBonds, const_cast<Bond*>(bond), this) ||
  181.                 (bond && bond->order == Bond::eRealDisulfide)) {
  182.                 // set inter-molecule bonds' display list(s) if real bond or virtual disulfide created
  183.                 if (displayListOtherStart == OpenGLRenderer::NO_LIST) {
  184.                     displayListOtherStart = parentSet->lastDisplayList + 1;
  185.                     parentSet->lastDisplayList += nAlts;
  186.                 }
  187.             }
  188.         }
  189.     }
  190.     // if hets/solvent/i-m bonds present, add display lists to frames
  191.     if (displayListOtherStart != OpenGLRenderer::NO_LIST) {
  192.         for (int n=0; n<nAlts; ++n) {
  193.             parentSet->frameMap[firstNewFrame + n].push_back(displayListOtherStart + n);
  194.             parentSet->transformMap[displayListOtherStart + n] = &(object->transformToMaster);
  195.         }
  196.     }
  197.     // fill out secondary structure and domain maps from NCBI assigments (in feature block)
  198.     FeatureList::const_iterator l, le = features.end();
  199.     for (l=features.begin(); l!=le; ++l) {
  200.         if (l->GetObject().IsSetDescr()) {
  201.             // find and unpack NCBI sec. struc. or domain features
  202.             CBiostruc_feature_set::TDescr::const_iterator d, de = l->GetObject().GetDescr().end();
  203.             for (d=l->GetObject().GetDescr().begin(); d!=de; ++d) {
  204.                 if (d->GetObject().IsName()) {
  205.                     if (d->GetObject().GetName() == "NCBI assigned secondary structure")
  206.                         UnpackSecondaryStructureFeatures(l->GetObject());
  207.                     else if (d->GetObject().GetName() == "NCBI Domains")
  208.                         UnpackDomainFeatures(l->GetObject());
  209.                     break;
  210.                 }
  211.             }
  212.         }
  213.     }
  214.     // Assign a (new) domain ID to all residues in a chain, if there are not any domains
  215.     // already set; in other words, assume a chain with no given domain features is composed
  216.     // of a single domain.
  217.     list < int > moleculeIDs;
  218.     MoleculeMap::iterator m, me = molecules.end();
  219.     for (m=molecules.begin(); m!=me; ++m) {
  220.         if (m->second->IsProtein() || m->second->IsNucleotide())
  221.             moleculeIDs.push_back(m->first);
  222.     }
  223.     moleculeIDs.sort();    // assign in order of ID
  224.     list < int >::const_iterator id, ide = moleculeIDs.end();
  225.     for (id=moleculeIDs.begin(); id!=ide; ++id) {
  226.         int r;
  227.         Molecule *molecule = const_cast<Molecule*>(molecules[*id]);
  228.         for (r=0; r<molecule->residues.size(); ++r)
  229.             if (molecule->residueDomains[r] != Molecule::NO_DOMAIN_SET) break;
  230.         if (r == molecule->residues.size()) {
  231.             int domainID = ++((const_cast<StructureSet*>(parentSet))->nDomains);
  232.             ++(molecule->nDomains);
  233.             (const_cast<StructureObject*>(object))->domainMap[domainID] = molecule;
  234.             (const_cast<StructureObject*>(object))->domainID2MMDB[domainID] = -1;
  235.             for (r=0; r<molecule->residues.size(); ++r)
  236.                 molecule->residueDomains[r] = domainID;
  237.         }
  238.     }
  239. }
  240. void ChemicalGraph::UnpackDomainFeatures(const CBiostruc_feature_set& featureSet)
  241. {
  242.     TRACEMSG("unpacking NCBI domain features");
  243.     CBiostruc_feature_set::TFeatures::const_iterator f, fe = featureSet.GetFeatures().end();
  244.     for (f=featureSet.GetFeatures().begin(); f!=fe; ++f) {
  245.         if (f->GetObject().GetType() == CBiostruc_feature::eType_subgraph &&
  246.             f->GetObject().IsSetLocation() &&
  247.             f->GetObject().GetLocation().IsSubgraph() &&
  248.             f->GetObject().GetLocation().GetSubgraph().IsResidues() &&
  249.             f->GetObject().GetLocation().GetSubgraph().GetResidues().IsInterval()) {
  250.             // assign a "domain ID" successively (from 1) over the whole StructureSet
  251.             int domainID = ++((const_cast<StructureSet*>(parentSet))->nDomains);
  252.             // find molecule and set regions, warning about overlaps
  253.             Molecule *molecule = NULL;
  254.             CResidue_pntrs::TInterval::const_iterator i,
  255.                 ie = f->GetObject().GetLocation().GetSubgraph().GetResidues().GetInterval().end();
  256.             for (i=f->GetObject().GetLocation().GetSubgraph().GetResidues().GetInterval().begin(); i!=ie; ++i) {
  257.                 MoleculeMap::const_iterator m = molecules.find(i->GetObject().GetMolecule_id().Get());
  258.                 if (m == molecules.end() ||
  259.                     m->second->id !=    // check to make sure all intervals are on same molecule
  260.                         f->GetObject().GetLocation().GetSubgraph().GetResidues().GetInterval().
  261.                             front().GetObject().GetMolecule_id().Get()) {
  262.                     WARNINGMSG("Bad moleculeID in domain interval");
  263.                     continue;
  264.                 }
  265.                 molecule = const_cast<Molecule*>(m->second);
  266.                 for (int r=i->GetObject().GetFrom().Get()-1; r<=i->GetObject().GetTo().Get()-1; ++r) {
  267.                     if (r < 0 || r >= molecule->residues.size()) {
  268.                         ERRORMSG("Bad residue range in domain feature for moleculeID "
  269.                             << molecule->id << " residueID " << r+1);
  270.                         break;
  271.                     } else if (molecule->residueDomains[r] != Molecule::NO_DOMAIN_SET) {
  272.                         WARNINGMSG("Overlapping domain feature for moleculeID "
  273.                             << molecule->id << " residueID " << r+1);
  274.                         break;
  275.                     } else {
  276.                         molecule->residueDomains[r] = domainID;
  277.                     }
  278.                 }
  279.             }
  280.             if (molecule) {
  281.                 const StructureObject *object;
  282.                 if (!GetParentOfType(&object)) return;
  283.                 (const_cast<StructureObject*>(object))->domainMap[domainID] = molecule;
  284.                 (const_cast<StructureObject*>(object))->domainID2MMDB[domainID] =
  285.                     f->GetObject().GetId().Get();
  286.                 ++(molecule->nDomains);
  287.             }
  288.         }
  289.     }
  290. }
  291. void ChemicalGraph::UnpackSecondaryStructureFeatures(const CBiostruc_feature_set& featureSet)
  292. {
  293.     TRACEMSG("unpacking NCBI sec. struc. features");
  294.     CBiostruc_feature_set::TFeatures::const_iterator f, fe = featureSet.GetFeatures().end();
  295.     for (f=featureSet.GetFeatures().begin(); f!=fe; ++f) {
  296.         if ((f->GetObject().GetType() == CBiostruc_feature::eType_helix ||
  297.                 f->GetObject().GetType() == CBiostruc_feature::eType_strand) &&
  298.             f->GetObject().IsSetLocation() &&
  299.             f->GetObject().GetLocation().IsSubgraph() &&
  300.             f->GetObject().GetLocation().GetSubgraph().IsResidues() &&
  301.             f->GetObject().GetLocation().GetSubgraph().GetResidues().IsInterval()) {
  302.             // find molecule and set region, warning about overlaps
  303.             if (f->GetObject().GetLocation().GetSubgraph().GetResidues().GetInterval().size() > 1) {
  304.                 WARNINGMSG("Can't deal with multi-interval sec. struc. regions");
  305.                 continue;
  306.             }
  307.             const CResidue_interval_pntr& interval =
  308.                 f->GetObject().GetLocation().GetSubgraph().GetResidues().GetInterval().front().GetObject();
  309.             MoleculeMap::const_iterator m = molecules.find(interval.GetMolecule_id().Get());
  310.             if (m == molecules.end()) {
  311.                 WARNINGMSG("Bad moleculeID in sec. struc. interval");
  312.                 continue;
  313.             }
  314.             Molecule *molecule = const_cast<Molecule*>(m->second);
  315.             for (int r=interval.GetFrom().Get()-1; r<=interval.GetTo().Get()-1; ++r) {
  316.                 if (r < 0 || r >= molecule->residues.size()) {
  317.                     ERRORMSG("Bad residue range in sec. struc. feature for moleculeID "
  318.                         << molecule->id << " residueID " << r+1);
  319.                     break;
  320.                 } if (molecule->residueSecondaryStructures[r] != Molecule::eCoil) {
  321.                     WARNINGMSG("Overlapping sec. struc. feature at moleculeID "
  322.                         << molecule->id << " residueID " << r+1);
  323.                 } else {
  324.                     molecule->residueSecondaryStructures[r] =
  325.                         (f->GetObject().GetType() == CBiostruc_feature::eType_helix) ?
  326.                             Molecule::eHelix : Molecule::eStrand;
  327.                 }
  328.             }
  329.         }
  330.     }
  331. }
  332. static int moleculeToRedraw = -1;
  333. void ChemicalGraph::RedrawMolecule(int moleculeID) const
  334. {
  335.     moleculeToRedraw = moleculeID;
  336.     DrawAll(NULL);
  337.     moleculeToRedraw = -1;
  338. }
  339. // This is where the work of breaking objects up into display lists gets done.
  340. bool ChemicalGraph::DrawAll(const AtomSet *ignored) const
  341. {
  342.     const StructureObject *object;
  343.     if (!GetParentOfType(&object)) return false;
  344.     if (moleculeToRedraw != -1)
  345.         TRACEMSG("drawing molecule " << moleculeToRedraw
  346.             << " of ChemicalGraph of object " << object->pdbID);
  347.     else
  348.         TRACEMSG("drawing ChemicalGraph of object " << object->pdbID);
  349.     // put each protein (with its 3d-objects) or nucleotide chain in its own display list
  350.     bool continueDraw;
  351.     AtomSetList::const_iterator a, ae=atomSetList.end();
  352.     MoleculeMap::const_iterator m, me=molecules.end();
  353.     for (m=molecules.begin(); m!=me; ++m) {
  354.         if (!m->second->IsProtein() && !m->second->IsNucleotide()) continue;
  355.         if (moleculeToRedraw >= 0 && m->second->id != moleculeToRedraw) continue;
  356.         Molecule::DisplayListList::const_iterator md=m->second->displayLists.begin();
  357.         for (a=atomSetList.begin(); a!=ae; ++a, ++md) {
  358.             // start new display list
  359.             //TESTMSG("drawing molecule #" << m->second->id << " + its objects in display list " << *md
  360.             //        << " of " << atomSetList.size());
  361.             parentSet->renderer->StartDisplayList(*md);
  362.             // draw this molecule with all alternative AtomSets (e.g., NMR's or altConfs)
  363.             a->first->SetActiveEnsemble(a->second);
  364.             continueDraw = m->second->DrawAllWithTerminiLabels(a->first);
  365.             if (continueDraw) {
  366.                 // find 3D objects for this molecule/CoordSet
  367.                 const CoordSet *coordSet;
  368.                 if (a->first->GetParentOfType(&coordSet)) {
  369.                     CoordSet::Object3DMap::const_iterator objList = coordSet->objectMap.find(m->second->id);
  370.                     if (objList != coordSet->objectMap.end()) {
  371.                         CoordSet::Object3DList::const_iterator o, oe=objList->second.end();
  372.                         for (o=objList->second.begin(); o!=oe; ++o) {
  373.                             if (!(continueDraw = (*o)->Draw(a->first))) break;
  374.                         }
  375.                     }
  376.                 }
  377.             }
  378.             // end display list
  379.             parentSet->renderer->EndDisplayList();
  380.             if (!continueDraw) return false;
  381.         }
  382.         // we're done if this was the single molecule meant to be redrawn
  383.         if (moleculeToRedraw >= 0) break;
  384.     }
  385.     // then put everything else (solvents, hets, and intermolecule bonds) in a single display list
  386.     if (displayListOtherStart == OpenGLRenderer::NO_LIST) return true;
  387.     //TESTMSG("drawing hets/solvents/i-m bonds");
  388.     // always redraw all these even if only a single molecule is to be redrawn -
  389.     // that way connections can show/hide in cases where a particular residue
  390.     // changes its display
  391.     int n = 0;
  392.     for (a=atomSetList.begin(); a!=ae; ++a, ++n) {
  393.         a->first->SetActiveEnsemble(a->second);
  394.         parentSet->renderer->StartDisplayList(displayListOtherStart + n);
  395.         for (m=molecules.begin(); m!=me; ++m) {
  396.             if (m->second->IsProtein() || m->second->IsNucleotide()) continue;
  397.             if (!(continueDraw = m->second->DrawAll(a->first))) break;
  398.         }
  399.         if (continueDraw) {
  400.             BondList::const_iterator b, be=interMoleculeBonds.end();
  401.             for (b=interMoleculeBonds.begin(); b!=be; ++b) {
  402.                 if (!(continueDraw = (*b)->Draw(a->first))) break;
  403.             }
  404.         }
  405.         parentSet->renderer->EndDisplayList();
  406.         if (!continueDraw) return false;
  407.     }
  408.     return true;
  409. }
  410. bool ChemicalGraph::CheckForDisulfide(const Molecule *molecule,
  411.     const CAtom_pntr& atomPtr1, const CAtom_pntr& atomPtr2,
  412.     list < const Bond * > *bondList, Bond *bond, StructureBase *parent)
  413. {
  414.     if (atomPtr1.GetMolecule_id().Get() == atomPtr2.GetMolecule_id().Get() &&
  415.         atomPtr1.GetResidue_id().Get() == atomPtr2.GetResidue_id().Get()) return false;
  416.     const Molecule *mol1, *mol2;
  417.     if (molecule) { // when called from Molecule::Molecule() on interresidue (intramolecular) bond
  418.         mol1 = mol2 = molecule;
  419.     } else {        // when called from ChemicalGraph::ChemicalGraph() on intermolecule bond
  420.         MoleculeMap::const_iterator
  421.             m1 = molecules.find(atomPtr1.GetMolecule_id().Get()),
  422.             m2 = molecules.find(atomPtr2.GetMolecule_id().Get());
  423.         if (m1 == molecules.end() || m2 == molecules.end()) {
  424.             ERRORMSG("ChemicalGraph::CheckForDisulfide() - bad molecule ID");
  425.             return false;
  426.         }
  427.         mol1 = m1->second;
  428.         mol2 = m2->second;
  429.     }
  430.     Molecule::ResidueMap::const_iterator
  431.         res1 = mol1->residues.find(atomPtr1.GetResidue_id().Get()),
  432.         res2 = mol2->residues.find(atomPtr2.GetResidue_id().Get());
  433.     if (res1 == mol1->residues.end() || res2 == mol2->residues.end()) {
  434.         ERRORMSG("ChemicalGraph::CheckForDisulfide() - bad residue ID");
  435.         return false;
  436.     }
  437.     // check to make sure both residues are cysteine
  438.     if (res1->second->type != Residue::eAminoAcid || res1->second->code != 'C' ||
  439.         res2->second->type != Residue::eAminoAcid || res2->second->code != 'C') return false;
  440.     const Residue::AtomInfo
  441.         *atom1 = res1->second->GetAtomInfo(atomPtr1.GetAtom_id().Get()),
  442.         *atom2 = res2->second->GetAtomInfo(atomPtr2.GetAtom_id().Get());
  443.     if (!atom1 || !atom2) {
  444.         ERRORMSG("ChemicalGraph::CheckForDisulfide() - bad atom ID");
  445.         return false;
  446.     }
  447.     // check to make sure both atoms are sulfur, and that residue has an alpha
  448.     if (atom1->atomicNumber != 16 || res1->second->alphaID == Residue::NO_ALPHA_ID ||
  449.         atom2->atomicNumber != 16 || res2->second->alphaID == Residue::NO_ALPHA_ID) return false;
  450.     TRACEMSG("found disulfide between molecule " << atomPtr1.GetMolecule_id().Get()
  451.         << " residue " << atomPtr1.GetResidue_id().Get()
  452.         << " and molecule " << atomPtr2.GetMolecule_id().Get()
  453.         << " residue " << atomPtr2.GetResidue_id().Get());
  454.     // first flag this bond as "real disulfide", so it's not drawn with connection style
  455.     if (bond) bond->order = Bond::eRealDisulfide;
  456.     // then, make a new virtual disulfide bond between the alphas of these residues
  457.     const Bond *virtualDisulfide = MakeBond(parent,
  458.         atomPtr1.GetMolecule_id().Get(), atomPtr1.GetResidue_id().Get(), res1->second->alphaID,
  459.         atomPtr2.GetMolecule_id().Get(), atomPtr2.GetResidue_id().Get(), res2->second->alphaID,
  460.         Bond::eVirtualDisulfide);
  461.     if (!virtualDisulfide) return false;
  462.     bondList->push_back(virtualDisulfide);
  463.     return true;
  464. }
  465. END_SCOPE(Cn3D)
  466. /*
  467. * ---------------------------------------------------------------------------
  468. * $Log: chemical_graph.cpp,v $
  469. * Revision 1000.2  2004/06/01 18:28:03  gouriano
  470. * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.40
  471. *
  472. * Revision 1.40  2004/05/21 21:41:39  gorelenk
  473. * Added PCH ncbi_pch.hpp
  474. *
  475. * Revision 1.39  2004/03/15 18:19:23  thiessen
  476. * prefer prefix vs. postfix ++/-- operators
  477. *
  478. * Revision 1.38  2004/02/19 17:04:46  thiessen
  479. * remove cn3d/ from include paths; add pragma to disable annoying msvc warning
  480. *
  481. * Revision 1.37  2003/08/21 17:56:29  thiessen
  482. * change header order for Mac compilation
  483. *
  484. * Revision 1.36  2003/06/21 21:04:41  thiessen
  485. * draw per-model 3D objects
  486. *
  487. * Revision 1.35  2003/03/06 19:23:18  thiessen
  488. * minor tweaks
  489. *
  490. * Revision 1.34  2003/02/03 19:20:02  thiessen
  491. * format changes: move CVS Log to bottom of file, remove std:: from .cpp files, and use new diagnostic macros
  492. *
  493. * Revision 1.33  2002/05/31 14:51:28  thiessen
  494. * small tweaks
  495. *
  496. * Revision 1.32  2002/03/18 15:17:29  thiessen
  497. * fix minor omission
  498. *
  499. * Revision 1.31  2001/12/12 14:04:13  thiessen
  500. * add missing object headers after object loader change
  501. *
  502. * Revision 1.30  2001/11/27 16:26:07  thiessen
  503. * major update to data management system
  504. *
  505. * Revision 1.29  2001/08/21 01:10:45  thiessen
  506. * add labeling
  507. *
  508. * Revision 1.28  2001/07/27 13:52:47  thiessen
  509. * make sure domains are assigned in order of molecule id; tweak pattern dialog
  510. *
  511. * Revision 1.27  2001/07/12 17:35:15  thiessen
  512. * change domain mapping ; add preliminary cdd annotation GUI
  513. *
  514. * Revision 1.26  2001/06/21 02:02:33  thiessen
  515. * major update to molecule identification and highlighting ; add toggle highlight (via alt)
  516. *
  517. * Revision 1.25  2001/05/31 18:47:07  thiessen
  518. * add preliminary style dialog; remove LIST_TYPE; add thread single and delete all; misc tweaks
  519. *
  520. * Revision 1.24  2001/05/18 22:58:52  thiessen
  521. * fix display list bug with disulfides
  522. *
  523. * Revision 1.23  2001/03/23 23:31:56  thiessen
  524. * keep atom info around even if coords not all present; mainly for disulfide parsing in virtual models
  525. *
  526. * Revision 1.22  2001/03/23 04:18:52  thiessen
  527. * parse and display disulfides
  528. *
  529. * Revision 1.21  2001/02/13 01:03:56  thiessen
  530. * backward-compatible domain ID's in output; add ability to delete rows
  531. *
  532. * Revision 1.20  2001/02/08 23:01:48  thiessen
  533. * hook up C-toolkit stuff for threading; working PSSM calculation
  534. *
  535. * Revision 1.19  2000/12/20 23:47:47  thiessen
  536. * load CDD's
  537. *
  538. * Revision 1.18  2000/12/19 16:39:08  thiessen
  539. * tweaks to show/hide
  540. *
  541. * Revision 1.17  2000/12/01 19:35:56  thiessen
  542. * better domain assignment; basic show/hide mechanism
  543. *
  544. * Revision 1.16  2000/11/30 15:49:36  thiessen
  545. * add show/hide rows; unpack sec. struc. and domain features
  546. *
  547. * Revision 1.15  2000/11/02 16:56:01  thiessen
  548. * working editor undo; dynamic slave transforms
  549. *
  550. * Revision 1.14  2000/09/14 14:55:34  thiessen
  551. * add row reordering; misc fixes
  552. *
  553. * Revision 1.13  2000/09/11 01:46:14  thiessen
  554. * working messenger for sequence<->structure window communication
  555. *
  556. * Revision 1.12  2000/08/27 18:52:20  thiessen
  557. * extract sequence information
  558. *
  559. * Revision 1.11  2000/08/21 17:22:37  thiessen
  560. * add primitive highlighting for testing
  561. *
  562. * Revision 1.10  2000/08/17 14:24:05  thiessen
  563. * added working StyleManager
  564. *
  565. * Revision 1.9  2000/08/16 14:18:44  thiessen
  566. * map 3-d objects to molecules
  567. *
  568. * Revision 1.8  2000/08/13 02:43:00  thiessen
  569. * added helix and strand objects
  570. *
  571. * Revision 1.7  2000/08/07 14:13:15  thiessen
  572. * added animation frames
  573. *
  574. * Revision 1.6  2000/08/07 00:21:17  thiessen
  575. * add display list mechanism
  576. *
  577. * Revision 1.5  2000/08/03 15:12:23  thiessen
  578. * add skeleton of style and show/hide managers
  579. *
  580. * Revision 1.4  2000/07/27 13:30:51  thiessen
  581. * remove 'using namespace ...' from all headers
  582. *
  583. * Revision 1.3  2000/07/16 23:19:10  thiessen
  584. * redo of drawing system
  585. *
  586. * Revision 1.2  2000/07/12 23:27:49  thiessen
  587. * now draws basic CPK model
  588. *
  589. * Revision 1.1  2000/07/11 13:45:29  thiessen
  590. * add modules to parse chemical graph; many improvements
  591. *
  592. */