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

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: residue.cpp,v $
  4.  * PRODUCTION Revision 1000.2  2004/06/01 18:29:02  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.34
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /*  $Id: residue.cpp,v 1000.2 2004/06/01 18:29:02 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 residues
  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/Residue_graph_pntr.hpp>
  47. #include <objects/mmdb1/Biost_resid_graph_set_pntr.hpp>
  48. #include <objects/general/Dbtag.hpp>
  49. #include <objects/mmdb1/Biomol_descr.hpp>
  50. #include <objects/mmdb1/Intra_residue_bond.hpp>
  51. #include <objects/mmdb1/Atom.hpp>
  52. #include <objects/mmdb1/Biostruc_id.hpp>
  53. #include <objects/mmdb1/Residue_id.hpp>
  54. #include <objects/general/Object_id.hpp>
  55. #include <objects/mmdb1/Residue_graph_id.hpp>
  56. #include <objects/mmdb1/Atom_id.hpp>
  57. #include "residue.hpp"
  58. #include "bond.hpp"
  59. #include "structure_set.hpp"
  60. #include "coord_set.hpp"
  61. #include "atom_set.hpp"
  62. #include "molecule.hpp"
  63. #include "periodic_table.hpp"
  64. #include "opengl_renderer.hpp"
  65. #include "style_manager.hpp"
  66. #include "cn3d_colors.hpp"
  67. #include "show_hide_manager.hpp"
  68. #include "cn3d_tools.hpp"
  69. #include "messenger.hpp"
  70. USING_NCBI_SCOPE;
  71. USING_SCOPE(objects);
  72. BEGIN_SCOPE(Cn3D)
  73. const char Residue::NO_CODE = '?';
  74. const int Residue::NO_ALPHA_ID = -1;
  75. static Residue::eAtomClassification ClassifyAtom(const Residue *residue, const CAtom& atom)
  76. {
  77.     if (!atom.IsSetIupac_code()) return Residue::eUnknownAtom;
  78.     string code = atom.GetIupac_code().front();
  79.     CAtom::EElement element = atom.GetElement();
  80.     if (residue->IsAminoAcid()) {
  81.         // amino acid C-alpha
  82.         if (element==CAtom::eElement_c && code==" CA ")
  83.             return Residue::eAlphaBackboneAtom;
  84.         // amino acid partial backbone
  85.         if (
  86.             (element==CAtom::eElement_c && code==" C  ") ||
  87.             (element==CAtom::eElement_n && code==" N  ")
  88.            )
  89.             return Residue::ePartialBackboneAtom;
  90.         // amino acid complete backbone (all backbone that's not part of "partial")
  91.         // including both GLY alpha hydrogens and terminal COOH and NH3+
  92.         if (
  93.             (element==CAtom::eElement_o &&
  94.                 (code==" O  " || code==" OXT")) ||
  95.             (element==CAtom::eElement_h &&
  96.                 (code==" H  " || code==" HA " || code=="1HA " || code=="2HA " ||
  97.                  code==" HXT" || code=="1H  " || code=="2H  " || code=="3H  "))
  98.             )
  99.             return Residue::eCompleteBackboneAtom;
  100.         // anything else is side chain
  101.         return Residue::eSideChainAtom;
  102.     } else if (residue->IsNucleotide()) {
  103.         // nucleic acid Phosphorus
  104.         if (element==CAtom::eElement_p && code==" P  ")
  105.             return Residue::eAlphaBackboneAtom;
  106.         // nucleic acid partial backbone
  107.         if (
  108.             (element==CAtom::eElement_c && (code==" C5*" || code==" C4*" || code==" C3*")) ||
  109.             (element==CAtom::eElement_o && (code==" O5*" || code==" O3*")) ||
  110.             (element==CAtom::eElement_h && (code==" H3T" || code==" H5T"))
  111.            )
  112.             return Residue::ePartialBackboneAtom;
  113.         // nucleic acid complete backbone (all backbone that's not part of "partial")
  114.         if (
  115.             (element==CAtom::eElement_o &&
  116.                 (code==" O1P" || code==" O2P" || code==" O4*" || code==" O2*")) ||
  117.             (element==CAtom::eElement_c && (code==" C2*" || code==" C1*")) ||
  118.             (element==CAtom::eElement_h &&
  119.                 (code=="1H5*" || code=="2H5*" || code==" H4*" || code==" H3*" ||
  120.                  code==" H2*" || code==" H1*" || code==" H1P" || code==" H2P" ||
  121.                  code==" HO2" || code=="1H2*" || code=="2H2*"))
  122.            )
  123.             return Residue::eCompleteBackboneAtom;
  124.         // anything else is side chain
  125.         return Residue::eSideChainAtom;
  126.     }
  127.     return Residue::eUnknownAtom;
  128. }
  129. Residue::Residue(StructureBase *parent,
  130.     const CResidue& residue, int moleculeID,
  131.     const ResidueGraphList& standardDictionary,
  132.     const ResidueGraphList& localDictionary) :
  133.     StructureBase(parent), code(NO_CODE), alphaID(NO_ALPHA_ID), type(eOther)
  134. {
  135.     // get ID
  136.     id = residue.GetId().Get();
  137.     // get Residue name
  138.     if (residue.IsSetName()) namePDB = residue.GetName();
  139.     // get CResidue_graph*
  140.     // standard (of correct type) or local dictionary?
  141.     const ResidueGraphList *dictionary;
  142.     int graphID;
  143.     if (residue.GetResidue_graph().IsStandard() &&
  144.         residue.GetResidue_graph().GetStandard().GetBiostruc_residue_graph_set_id().IsOther_database() &&
  145.         residue.GetResidue_graph().GetStandard().GetBiostruc_residue_graph_set_id().GetOther_database().GetDb() == "Standard residue dictionary" &&
  146.         residue.GetResidue_graph().GetStandard().GetBiostruc_residue_graph_set_id().GetOther_database().GetTag().IsId() &&
  147.         residue.GetResidue_graph().GetStandard().GetBiostruc_residue_graph_set_id().GetOther_database().GetTag().GetId() == 1) {
  148.         dictionary = &standardDictionary;
  149.         graphID = residue.GetResidue_graph().GetStandard().GetResidue_graph_id().Get();
  150.     } else if (residue.GetResidue_graph().IsLocal()) {
  151.         dictionary = &localDictionary;
  152.         graphID = residue.GetResidue_graph().GetLocal().Get();
  153.     } else
  154.         ERRORMSG("confused by Molecule #?, Residue #" << id << "; can't find appropriate dictionary");
  155.     // look up appropriate Residue_graph
  156.     const CResidue_graph *residueGraph = NULL;
  157.     ResidueGraphList::const_iterator i, ie=dictionary->end();
  158.     for (i=dictionary->begin(); i!=ie; ++i) {
  159.         if (i->GetObject().GetId().Get() == graphID) {
  160.             residueGraph = i->GetPointer();
  161.             break;
  162.         }
  163.     }
  164.     if (!residueGraph)
  165.         ERRORMSG("confused by Molecule #?, Residue #" << id << "; can't find Residue-graph ID #" << graphID);
  166.     // get iupac-code if present - assume it's the first character of the first VisibleString
  167.     if (residueGraph->IsSetIupac_code())
  168.         code = residueGraph->GetIupac_code().front()[0];
  169.     // get residue-graph name if present
  170.     if (residueGraph->IsSetDescr()) {
  171.         CResidue_graph::TDescr::const_iterator j, je = residueGraph->GetDescr().end();
  172.         for (j=residueGraph->GetDescr().begin(); j!=je; ++j) {
  173.             if (j->GetObject().IsName()) {
  174.                 nameGraph = j->GetObject().GetName();
  175.                 break;
  176.             }
  177.         }
  178.     }
  179.     // get type
  180.     if (residueGraph->IsSetResidue_type())
  181.         type = static_cast<eType>(residueGraph->GetResidue_type());
  182.     // get StructureObject* parent
  183.     const StructureObject *object;
  184.     if (!GetParentOfType(&object) || object->coordSets.size() == 0) {
  185.         ERRORMSG("Residue()::Residue() : parent doesn't have any CoordSets");
  186.         return;
  187.     }
  188.     // get atom info
  189.     nAtomsWithAnyCoords = 0;
  190.     CResidue_graph::TAtoms::const_iterator a, ae = residueGraph->GetAtoms().end();
  191.     for (a=residueGraph->GetAtoms().begin(); a!=ae; ++a) {
  192.         const CAtom& atom = a->GetObject();
  193.         int atomID = atom.GetId().Get();
  194.         AtomInfo *info = new AtomInfo;
  195.         AtomPntr ap(moleculeID, id, atomID);
  196.         // see if this atom is present in any CoordSet
  197.         StructureObject::CoordSetList::const_iterator c, ce=object->coordSets.end();
  198.         for (c=object->coordSets.begin(); c!=ce; ++c) {
  199.             if (((*c)->atomSet->GetAtom(ap, true, true))) {
  200.                 ++nAtomsWithAnyCoords;
  201.                 break;
  202.             }
  203.         }
  204.         info->residue = this;
  205.         // get name if present
  206.         if (atom.IsSetName()) info->name = atom.GetName();
  207.         // get code if present - just use first one of the SEQUENCE
  208.         if (atom.IsSetIupac_code())
  209.             info->code = atom.GetIupac_code().front();
  210.         // get atomic number, assuming it's the integer value of the enumerated type
  211.         CAtom_Base::EElement atomicNumber = atom.GetElement();
  212.         info->atomicNumber = static_cast<int>(atomicNumber);
  213.         // get ionizable status
  214.         if (atom.IsSetIonizable_proton() &&
  215.             atom.GetIonizable_proton() == CAtom::eIonizable_proton_true)
  216.             info->isIonizableProton = true;
  217.         else
  218.             info->isIonizableProton = false;
  219.         // assign (unique) name
  220.         info->glName = parentSet->CreateName(this, atomID);
  221.         // classify atom
  222.         info->classification = ClassifyAtom(this, atom);
  223.         // store alphaID in residue
  224.         if (info->classification == eAlphaBackboneAtom) alphaID = atomID;
  225.         // add info to map
  226.         if (atomInfos.find(atom.GetId().Get()) != atomInfos.end())
  227.             ERRORMSG("Residue #" << id << ": confused by multiple atom IDs " << atom.GetId().Get());
  228.         atomInfos[atomID] = info;
  229.     }
  230.     // get bonds
  231.     CResidue_graph::TBonds::const_iterator b, be = residueGraph->GetBonds().end();
  232.     for (b=residueGraph->GetBonds().begin(); b!=be; ++b) {
  233.         int order = b->GetObject().IsSetBond_order() ?
  234.                 b->GetObject().GetBond_order() : Bond::eUnknown;
  235.         const Bond *bond = MakeBond(this,
  236.             moleculeID, id, b->GetObject().GetAtom_id_1().Get(),
  237.             moleculeID, id, b->GetObject().GetAtom_id_2().Get(),
  238.             order);
  239.         if (bond) bonds.push_back(bond);
  240.     }
  241. }
  242. Residue::~Residue(void)
  243. {
  244.     AtomInfoMap::iterator a, ae = atomInfos.end();
  245.     for (a=atomInfos.begin(); a!=ae; ++a) delete a->second;
  246. }
  247. // draw atom spheres and residue labels here
  248. bool Residue::Draw(const AtomSet *atomSet) const
  249. {
  250.     if (!atomSet) {
  251.         ERRORMSG("Residue::Draw(data) - NULL AtomSet*");
  252.         return false;
  253.     }
  254.     // verify presense of OpenGLRenderer
  255.     if (!parentSet->renderer) {
  256.         WARNINGMSG("Residue::Draw() - no renderer");
  257.         return false;
  258.     }
  259.     // get Molecule parent
  260.     const Molecule *molecule;
  261.     if (!GetParentOfType(&molecule)) return false;
  262.     // get object parent
  263.     const StructureObject *object;
  264.     if (!GetParentOfType(&object)) return false;
  265.     // is this residue labeled?
  266.     const StyleSettings& settings = parentSet->styleManager->GetStyleForResidue(object, molecule->id, id);
  267.     bool proteinLabel = (IsAminoAcid() && settings.proteinLabels.spacing > 0 &&
  268.         (id-1)%settings.proteinLabels.spacing == 0);
  269.     bool nucleotideLabel = (IsNucleotide() && settings.nucleotideLabels.spacing > 0 &&
  270.         (id-1)%settings.nucleotideLabels.spacing == 0);
  271.     bool overlayEnsembles = parentSet->showHideManager->OverlayConfEnsembles();
  272.     AtomStyle atomStyle;
  273.     const AtomCoord *atom, *l1 = NULL, *l2 = NULL, *l3 = NULL;
  274.     Vector labelColor;
  275.     bool alphaVisible = false, alphaOnly = false;
  276.     // iterate atoms; key is atomID
  277.     AtomInfoMap::const_iterator a, ae = atomInfos.end();
  278.     for (a=atomInfos.begin(); a!=ae; ++a) {
  279.         // get AtomCoord* for appropriate altConf
  280.         AtomPntr ap(molecule->id, id, a->first);
  281.         atom = atomSet->GetAtom(ap, overlayEnsembles, true);
  282.         if (!atom) continue;
  283.         // get Style
  284.         if (!parentSet->styleManager->GetAtomStyle(this, ap, atom, &atomStyle))
  285.             return false;
  286.         // highlight atom if necessary
  287.         if (atomStyle.isHighlighted)
  288.             atomStyle.color = GlobalColors()->Get(Colors::eHighlight);
  289.         // draw the atom
  290.         if (atomStyle.style != StyleManager::eNotDisplayed && atomStyle.radius > 0.0)
  291.             parentSet->renderer->DrawAtom(atom->site, atomStyle);
  292.         // store coords for positioning label, based on backbone coordinates
  293.         if ((proteinLabel || nucleotideLabel) && a->second->classification != eSideChainAtom) {
  294.             if (IsAminoAcid()) {
  295.                 if (a->second->name == " CA ") {
  296.                     l1 = atom;
  297.                     labelColor = atomStyle.color;
  298.                     alphaVisible = (atomStyle.style != StyleManager::eNotDisplayed);
  299.                 }
  300.                 else if (a->second->name == " C  ") l2 = atom;
  301.                 else if (a->second->name == " N  ") l3 = atom;
  302.             } else if (IsNucleotide()) {
  303.                 if (a->second->name == " P  ") {
  304.                     l1 = atom;
  305.                     labelColor = atomStyle.color;
  306.                     alphaVisible = (atomStyle.style != StyleManager::eNotDisplayed);
  307.                 }
  308.                 // labeling by alphas seems to work better for nucleotides
  309. //                else if (a->second->name == " C4*") l2 = atom;
  310. //                else if (a->second->name == " C5*") l3 = atom;
  311.             }
  312.         }
  313.     }
  314.     // if not all backbone atoms present (e.g. alpha only), use alpha coords of neighboring residues
  315.     if (l1 && (!l2 || !l3)) {
  316.         Molecule::ResidueMap::const_iterator prevRes, nextRes;
  317.         const AtomCoord *prevAlpha, *nextAlpha;
  318.         if ((prevRes=molecule->residues.find(id - 1)) != molecule->residues.end() &&
  319.             prevRes->second->alphaID != NO_ALPHA_ID &&
  320.             (prevAlpha=atomSet->GetAtom(AtomPntr(molecule->id, id - 1, prevRes->second->alphaID))) != NULL &&
  321.             (nextRes=molecule->residues.find(id + 1)) != molecule->residues.end() &&
  322.             nextRes->second->alphaID != NO_ALPHA_ID &&
  323.             (nextAlpha=atomSet->GetAtom(AtomPntr(molecule->id, id + 1, nextRes->second->alphaID))) != NULL)
  324.         {
  325.             l2 = prevAlpha;
  326.             l3 = nextAlpha;
  327.             alphaOnly = true;
  328.         }
  329.     }
  330.     // draw residue (but not terminus) labels, assuming we have the necessary coordinates and
  331.     // that alpha atoms are visible
  332.     if (alphaVisible && (proteinLabel|| nucleotideLabel)) {
  333.         Vector labelPosition;
  334.         CNcbiOstrstream oss;
  335.         double contrast = Colors::IsLightColor(settings.backgroundColor) ? 0 : 1;
  336.         // protein label
  337.         if (IsAminoAcid() && l1 && l2 && l3) {
  338.             // position
  339.             if (alphaOnly) {
  340.                 Vector forward = - ((l2->site - l1->site) + (l3->site - l1->site));
  341.                 forward.normalize();
  342.                 labelPosition = l1->site + 1.5 * forward;
  343.             } else {
  344.                 Vector up = vector_cross(l2->site - l1->site, l3->site - l1->site);
  345.                 up.normalize();
  346.                 Vector forward = (-((l2->site - l1->site) + (l3->site - l1->site)) / 2);
  347.                 forward.normalize();
  348.                 labelPosition = l1->site + 1.5 * forward + 1.5 * up;
  349.             }
  350.             // text
  351.             if (settings.proteinLabels.type == StyleSettings::eOneLetter) {
  352.                 oss << code;
  353.             } else if (settings.proteinLabels.type == StyleSettings::eThreeLetter) {
  354.                 for (int i=0; i<nameGraph.size() && i<3; ++i)
  355.                     oss << ((i == 0) ? (char) toupper(nameGraph[0]) : (char) tolower(nameGraph[i]));
  356.             }
  357.             // add number if necessary
  358.             if (settings.proteinLabels.numbering == StyleSettings::eSequentialNumbering)
  359.                 oss << ' ' << id;
  360.             else if (settings.proteinLabels.numbering == StyleSettings::ePDBNumbering)
  361.                 oss << namePDB;
  362.             // contrasting color? (default to CA's color)
  363.             if (settings.proteinLabels.white) labelColor.Set(contrast, contrast, contrast);
  364.         }
  365.         // nucleotide label
  366.         else if (IsNucleotide() && l2 && l3) {
  367.             if (alphaOnly) {
  368.                 Vector forward = - ((l2->site - l1->site) + (l3->site - l1->site));
  369.                 forward.normalize();
  370.                 labelPosition = l1->site + 3 * forward;
  371.             } else {
  372.                 labelPosition = l3->site + 3 * (l3->site - l2->site);
  373.             }
  374.             // text
  375.             if (settings.nucleotideLabels.type == StyleSettings::eOneLetter) {
  376.                 oss << code;
  377.             } else if (settings.nucleotideLabels.type == StyleSettings::eThreeLetter) {
  378.                 for (int i=0; i<3; ++i)
  379.                     if (nameGraph.size() > i && nameGraph[i] != ' ')
  380.                         oss << nameGraph[i];
  381.             }
  382.             // add number if necessary
  383.             if (settings.nucleotideLabels.numbering == StyleSettings::eSequentialNumbering)
  384.                 oss << ' ' << id;
  385.             else if (settings.nucleotideLabels.numbering == StyleSettings::ePDBNumbering)
  386.                 oss << namePDB;
  387.             // contrasting color? (default to C4*'s color)
  388.             if (settings.nucleotideLabels.white) labelColor.Set(contrast, contrast, contrast);
  389.         }
  390.         // draw label
  391.         if (oss.pcount() > 0) {
  392.             oss << '';
  393.             string labelText = oss.str();
  394.             delete oss.str();
  395.             // apply highlight color if necessary
  396.             if (GlobalMessenger()->IsHighlighted(molecule, id))
  397.                 labelColor = GlobalColors()->Get(Colors::eHighlight);
  398.             parentSet->renderer->DrawLabel(labelText, labelPosition, labelColor);
  399.         }
  400.     }
  401.     return true;
  402. }
  403. END_SCOPE(Cn3D)
  404. /*
  405. * ---------------------------------------------------------------------------
  406. * $Log: residue.cpp,v $
  407. * Revision 1000.2  2004/06/01 18:29:02  gouriano
  408. * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.34
  409. *
  410. * Revision 1.34  2004/05/21 21:41:39  gorelenk
  411. * Added PCH ncbi_pch.hpp
  412. *
  413. * Revision 1.33  2004/03/15 18:27:12  thiessen
  414. * prefer prefix vs. postfix ++/-- operators
  415. *
  416. * Revision 1.32  2004/02/19 17:05:05  thiessen
  417. * remove cn3d/ from include paths; add pragma to disable annoying msvc warning
  418. *
  419. * Revision 1.31  2003/06/21 08:18:58  thiessen
  420. * show all atoms with coordinates, even if not in all coord sets
  421. *
  422. * Revision 1.30  2003/02/03 19:20:05  thiessen
  423. * format changes: move CVS Log to bottom of file, remove std:: from .cpp files, and use new diagnostic macros
  424. *
  425. * Revision 1.29  2002/11/06 00:18:10  thiessen
  426. * fixes for new CRef/const rules in objects
  427. *
  428. * Revision 1.28  2001/12/12 14:04:14  thiessen
  429. * add missing object headers after object loader change
  430. *
  431. * Revision 1.27  2001/10/16 21:49:07  thiessen
  432. * restructure MultiTextDialog; allow virtual bonds for alpha-only PDB's
  433. *
  434. * Revision 1.26  2001/08/24 00:41:36  thiessen
  435. * tweak conservation colors and opengl font handling
  436. *
  437. * Revision 1.25  2001/08/21 01:10:45  thiessen
  438. * add labeling
  439. *
  440. * Revision 1.24  2001/08/09 19:07:13  thiessen
  441. * add temperature and hydrophobicity coloring
  442. *
  443. * Revision 1.23  2001/05/17 18:34:26  thiessen
  444. * spelling fixes; change dialogs to inherit from wxDialog
  445. *
  446. * Revision 1.22  2001/05/15 23:48:37  thiessen
  447. * minor adjustments to compile under Solaris/wxGTK
  448. *
  449. * Revision 1.21  2001/04/18 15:46:53  thiessen
  450. * show description, length, and PDB numbering in status line
  451. *
  452. * Revision 1.20  2001/03/23 23:31:56  thiessen
  453. * keep atom info around even if coords not all present; mainly for disulfide parsing in virtual models
  454. *
  455. * Revision 1.19  2001/03/22 00:33:17  thiessen
  456. * initial threading working (PSSM only); free color storage in undo stack
  457. *
  458. * Revision 1.18  2000/12/01 19:35:57  thiessen
  459. * better domain assignment; basic show/hide mechanism
  460. *
  461. * Revision 1.17  2000/11/30 15:49:39  thiessen
  462. * add show/hide rows; unpack sec. struc. and domain features
  463. *
  464. * Revision 1.16  2000/09/11 22:57:32  thiessen
  465. * working highlighting
  466. *
  467. * Revision 1.15  2000/08/25 14:22:00  thiessen
  468. * minor tweaks
  469. *
  470. * Revision 1.14  2000/08/19 02:59:05  thiessen
  471. * fix transparent sphere bug
  472. *
  473. * Revision 1.13  2000/08/18 18:57:39  thiessen
  474. * added transparent spheres
  475. *
  476. * Revision 1.12  2000/08/17 14:24:06  thiessen
  477. * added working StyleManager
  478. *
  479. * Revision 1.11  2000/08/13 02:43:01  thiessen
  480. * added helix and strand objects
  481. *
  482. * Revision 1.10  2000/08/11 12:58:31  thiessen
  483. * added worm; get 3d-object coords from asn1
  484. *
  485. * Revision 1.9  2000/08/07 00:21:18  thiessen
  486. * add display list mechanism
  487. *
  488. * Revision 1.8  2000/08/04 22:49:03  thiessen
  489. * add backbone atom classification and selection feedback mechanism
  490. *
  491. * Revision 1.7  2000/08/03 15:12:23  thiessen
  492. * add skeleton of style and show/hide managers
  493. *
  494. * Revision 1.6  2000/07/27 13:30:51  thiessen
  495. * remove 'using namespace ...' from all headers
  496. *
  497. * Revision 1.5  2000/07/17 22:37:18  thiessen
  498. * fix vector_math typo; correctly set initial view
  499. *
  500. * Revision 1.4  2000/07/17 11:59:16  thiessen
  501. * fix nucleotide virtual bonds
  502. *
  503. * Revision 1.3  2000/07/17 04:20:50  thiessen
  504. * now does correct structure alignment transformation
  505. *
  506. * Revision 1.2  2000/07/16 23:19:11  thiessen
  507. * redo of drawing system
  508. *
  509. * Revision 1.1  2000/07/11 13:45:31  thiessen
  510. * add modules to parse chemical graph; many improvements
  511. *
  512. */