Molmodel

Compound.h

Go to the documentation of this file.
00001 #ifndef SimTK_MOLMODEL_COMPOUND_H_
00002 #define SimTK_MOLMODEL_COMPOUND_H_
00003 
00004 /* -------------------------------------------------------------------------- *
00005  *                      SimTK Core: SimTK Molmodel                            *
00006  * -------------------------------------------------------------------------- *
00007  * This is part of the SimTK Core biosimulation toolkit originating from      *
00008  * Simbios, the NIH National Center for Physics-Based Simulation of           *
00009  * Biological Structures at Stanford, funded under the NIH Roadmap for        *
00010  * Medical Research, grant U54 GM072970. See https://simtk.org.               *
00011  *                                                                            *
00012  * Portions copyright (c) 2007-2008 Stanford University and the Authors.      *
00013  * Authors: Michael Sherman, Christopher Bruns                                *
00014  * Contributors:                                                              *
00015  *                                                                            *
00016  * Permission is hereby granted, free of charge, to any person obtaining a    *
00017  * copy of this software and associated documentation files (the "Software"), *
00018  * to deal in the Software without restriction, including without limitation  *
00019  * the rights to use, copy, modify, merge, publish, distribute, sublicense,   *
00020  * and/or sell copies of the Software, and to permit persons to whom the      *
00021  * Software is furnished to do so, subject to the following conditions:       *
00022  *                                                                            *
00023  * The above copyright notice and this permission notice shall be included in *
00024  * all copies or substantial portions of the Software.                        *
00025  *                                                                            *
00026  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
00027  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,   *
00028  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL    *
00029  * THE AUTHORS, CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,    *
00030  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR      *
00031  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE  *
00032  * USE OR OTHER DEALINGS IN THE SOFTWARE.                                     *
00033  * -------------------------------------------------------------------------- */
00034 
00035 
00036 #include "SimTKsimbody.h"
00037 
00038 #include "molmodel/internal/common.h"
00039 #include "DuMMForceFieldSubsystem.h"
00040 #include "molmodel/internal/Pdb.h"
00041 #include "molmodel/internal/Superpose.h"
00042 #include "molmodel/internal/units.h"
00043 #include <map>
00044 
00045 #include <iosfwd> // declare ostream without all the definitions
00046 
00047 namespace SimTK {
00048 class CompoundSystem;
00049 
00050 // Because of private data, put Compound implementation behind the curtain
00051 class Compound;
00052 class CompoundRep;
00053 
00054 // Make sure class is instantiated just once in the library
00055 // #ifndef DO_INSTANTIATE_COMPOUND_PIMPL_HANDLE
00056 //    template class SimTK_MOLMODEL_EXPORT PIMPLHandle<Compound, CompoundRep>;
00057 // #endif
00058 
00062 namespace BondMobility {
00070     enum Mobility {
00071         Free = 1, 
00072         Torsion = 2, 
00073         Rigid = 3 
00074     };
00075     static Mobility Default = Torsion;
00076 }
00077 
00084 class SimTK_MOLMODEL_EXPORT Compound : public PIMPLHandle<Compound,CompoundRep> {
00085 public:
00086 
00087     enum MatchStratagem {
00088         Match_Exact, //< Try to match input atom positions precisely
00089         Match_Idealized, //< Try to match atom positions with idealized geometry
00090         Match_TopologyOnly //< Don't match atom positions, only topology
00091     };
00092     
00095 
00101     typedef String Name;
00102 
00116     typedef String AtomName;
00117 
00128     typedef String BondCenterName;
00129 
00136     typedef String DihedralName;
00137 
00148     typedef String BondCenterPathName;
00149 
00163     typedef String AtomPathName;
00164 
00165     // Unique classes which behave like type-safe ints. These are local
00166     // to Compound.
00167 
00173     // SimTK_DEFINE_UNIQUE_LOCAL_INDEX_TYPE(Compound,Index);
00174 
00175 
00181     SimTK_DEFINE_UNIQUE_LOCAL_INDEX_TYPE(Compound,AtomIndex);
00182 
00188     SimTK_DEFINE_UNIQUE_LOCAL_INDEX_TYPE(Compound,LocalAtomIndex);
00189 
00195     SimTK_DEFINE_UNIQUE_LOCAL_INDEX_TYPE(Compound,BondCenterIndex);
00196 
00202     SimTK_DEFINE_UNIQUE_LOCAL_INDEX_TYPE(Compound,BondIndex);
00203 
00205     typedef std::map<AtomIndex, Vec3> AtomTargetLocations;
00206 
00207     class SingleAtom;
00208 
00210 
00211 
00214 
00220     Compound();
00221 
00229     explicit Compound(const Name& name 
00230         );
00231 
00235     int getNumAtoms() const;
00236 
00238     size_t getNumBondCenters() const;
00239 
00241     size_t getNumBondCenters(Compound::AtomIndex atomIndex) const;
00242 
00244     size_t getNumBonds() const;
00245 
00247     // int getNumSubcompounds() const;
00248 
00250     bool hasAtom(const AtomPathName& name 
00251         ) const;
00252 
00254     bool hasBondCenter(const BondCenterPathName& bondCenter 
00255         ) const;
00256 
00258     // bool hasSubcompound(const Name& name ///< name of the subcompound relative to this compound.
00259     //     ) const;
00260 
00262     Compound::AtomIndex getBondAtomIndex(
00263         Compound::BondIndex bondIndex, 
00264         int which                      
00265         ) const;
00266 
00267 
00273     Compound& setBaseAtom(
00274         const Compound::AtomName& name,   
00275         const Element& element,           
00276         const Transform& location = Vec3(0)  
00277         );
00283     Compound& setBaseAtom(
00284         const Compound::AtomName& name,   
00285         const Biotype& biotype,           
00286         const Transform& location = Vec3(0)    
00287         );  
00288 
00295     Compound& setBaseAtom(
00296         const Compound::SingleAtom& c, 
00297         const Transform& = Transform() 
00298         ); 
00299 
00305     Compound& setBaseCompound(
00306         const Compound::Name& n,         
00307         const Compound& c,               
00308         const Transform& location = Transform()
00309         );
00310 
00317     Compound& bondAtom(
00318         const Compound::SingleAtom& c, 
00319         const BondCenterPathName& parentBondName, 
00320         mdunits::Length distance, 
00321         Angle dihedral = 0, 
00322         BondMobility::Mobility = BondMobility::Default 
00323         );
00324 
00333     Compound& bondAtom(
00334         const Compound::SingleAtom& c, 
00335         const BondCenterPathName& parentBondName 
00336         );
00337 
00343     Compound& bondCompound(
00344         const Compound::Name& n, 
00345         const Compound& c, 
00346         const BondCenterPathName& parentBondName, 
00347         mdunits::Length distance, 
00348         Angle dihedral = 180*Deg2Rad, 
00349         BondMobility::Mobility mobility = BondMobility::Default 
00350         );
00351 
00361     Compound& bondCompound(
00362         const Compound::Name& n, 
00363         const Compound& c,  
00364         const BondCenterPathName& parentBondName 
00365         );
00366 
00376     Compound& bondCompound(
00377         const Compound::Name& n, 
00378         const Compound& c, 
00379         const BondCenterPathName& parentBondName,  
00380         BondMobility::Mobility mobility 
00381         );
00382 
00390     Compound& setInboardBondCenter(
00391         const Compound::BondCenterName& centerName 
00392         );
00393 
00399     Compound& convertInboardBondCenterToOutboard();
00400 
00406     Compound& addFirstBondCenter(
00407         const Compound::BondCenterName& centerName, 
00408         const Compound::AtomPathName& atomName 
00409         );
00410 
00417     Compound& addSecondBondCenter(
00418         const Compound::BondCenterName& centerName, 
00419         const Compound::AtomName& atomName, 
00420         Angle bondAngle1 
00421         );
00422 
00433     Compound& addPlanarBondCenter(
00434         const Compound::BondCenterName& centerName, 
00435         const Compound::AtomName& atomName, 
00436         Angle bondAngle1, 
00437         Angle bondAngle2 
00438         );
00439 
00449     Compound& addRightHandedBondCenter(
00450         const Compound::BondCenterName& centerName, 
00451         const Compound::AtomName& atomName, 
00452         Angle bondAngle1, 
00453         Angle bondAngle2 
00454         );
00455 
00465     Compound& addLeftHandedBondCenter(
00466         const Compound::BondCenterName& centerName, 
00467         const Compound::AtomName& atomName, 
00468         Angle bondAngle1, 
00469         Angle bondAngle2 
00470         );
00471 
00483     Compound& addRingClosingBond(
00484         const Compound::BondCenterPathName& centerName1, 
00485         const Compound::BondCenterPathName& centerName2, 
00486         mdunits::Length bondLength, 
00487         Angle dihedral = 180*Deg2Rad, 
00488         BondMobility::Mobility mobility = BondMobility::Default 
00489         );
00490 
00502     Compound& addRingClosingBond(
00503         const Compound::BondCenterPathName& centerName1, 
00504         const Compound::BondCenterPathName& centerName2 
00505         );
00506 
00508     //const Compound& getSubcompound(Compound::Index ///< integer index of subcompound
00509     //    ) const;
00510 
00512     //Compound& updSubcompound(Compound::Index ///< integer index of subcompound
00513     //    );
00514 
00516     const Compound& getSubcompound(const Compound::Name& subcompoundName 
00517         ) const;
00518 
00520     Compound& updSubcompound(const Compound::Name& subcompoundName 
00521         );
00522 
00524     // end topology methods
00525 
00526 
00529 
00535     Vec3 calcDefaultAtomLocationInGroundFrame(const AtomPathName& atomName 
00536         ) const;
00537 
00538     Vec3 calcDefaultAtomLocationInCompoundFrame(const AtomPathName& atomName 
00539         ) const;
00540 
00550     Compound& setDefaultInboardBondLength(mdunits::Length 
00551         );
00552 
00561     Compound& setDefaultInboardDihedralAngle(Angle 
00562         );
00563 
00572     Compound& setDefaultBondAngle(
00573         Angle angle, 
00574         const AtomPathName& atom1, 
00575         const AtomPathName& atom2, 
00576         const AtomPathName& atom3 
00577         );
00578 
00584     Compound& setDefaultBondLength(
00585         mdunits::Length length, 
00586         const AtomPathName& atom1, 
00587         const AtomPathName& atom2 
00588         );
00589 
00595     Compound& setDefaultDihedralAngle(
00596         const DihedralName& dihedralName, 
00597         Angle angleInRadians 
00598         );
00599 
00600     Compound& setDefaultDihedralAngle(
00601                 Angle angle, 
00602                 Compound::AtomIndex atom1,
00603                 Compound::AtomIndex atom2,
00604                 Compound::AtomIndex atom3,
00605                 Compound::AtomIndex atom4
00606                 );
00607     
00608     Compound& setDefaultDihedralAngle(
00609                 Angle angle, 
00610                 const Compound::AtomName& atom1,
00611                 const Compound::AtomName& atom2,
00612                 const Compound::AtomName& atom3,
00613                 const Compound::AtomName& atom4
00614                 );
00615     
00621     Angle calcDefaultDihedralAngle(
00622         const DihedralName& dihedralName 
00623         ) const;
00624 
00632     Compound& setDihedralAngle(
00633         State& state, 
00634         const DihedralName& dihedralName, 
00635         Angle 
00636         );
00637 
00643     Angle calcDihedralAngle(
00644         const State& state, 
00645         const DihedralName& dihedralName 
00646         ) const;
00647 
00649     Transform calcDefaultAtomFrameInCompoundFrame(Compound::AtomIndex 
00650         ) const;
00651 
00655     Vec3 calcAtomLocationInGroundFrame(
00656         const State& state, 
00657         Compound::AtomIndex atomId 
00658         ) const;
00659 
00660     Vec3 calcAtomLocationInCompoundFrame(
00661         const State& state, 
00662         Compound::AtomIndex atomId 
00663         ) const;
00664 
00668     Vec3 calcAtomVelocityInGroundFrame(
00669         const State& state, 
00670         Compound::AtomIndex atomId  
00671         ) const;
00672 
00676     Vec3 calcAtomAccelerationInGroundFrame(
00677         const State& state, 
00678         Compound::AtomIndex atomId   
00679         ) const;
00680 
00684     Transform getSubcompoundFrameInParentFrame(
00685         const Compound::Name& subcompoundName 
00686         ) const;
00687 
00693     virtual AtomTargetLocations createAtomTargets(const class PdbStructure& targetStructure) const;
00694     virtual AtomTargetLocations createAtomTargets(const class PdbChain& targetChain) const;
00695     virtual AtomTargetLocations createAtomTargets(const class PdbResidue& targetResidue) const;
00696 
00704     Compound& matchDefaultAtomChirality(
00705             const AtomTargetLocations& atomTargets, 
00706             Angle planarityTolerance = 90.0 * Deg2Rad, 
00707             bool flipAll = true 
00708             );
00709     Compound& matchDefaultBondLengths(const AtomTargetLocations& atomTargets);
00710     Compound& matchDefaultBondAngles(const AtomTargetLocations& atomTargets);
00711 
00712     enum PlanarBondMatchingPolicy {KeepPlanarBonds, DistortPlanarBonds, FlipPlanarBonds};
00713     Compound& matchDefaultDihedralAngles(
00714         const AtomTargetLocations& atomTargets,
00715         PlanarBondMatchingPolicy policy = FlipPlanarBonds 
00716         );
00717 
00718     Compound& matchDefaultTopLevelTransform(const AtomTargetLocations& atomTargets);
00719     TransformAndResidual getTransformAndResidual(const Compound::AtomTargetLocations& atomTargets) const;
00720     
00722     Compound& matchDefaultConfiguration(
00723             const AtomTargetLocations& atomTargets, 
00724             MatchStratagem matchStratagem = Match_Exact) 
00725     {
00726         if (matchStratagem == Compound::Match_TopologyOnly)
00727             // do nothing, topology is already there
00728             return *this;
00729         
00730         else if (matchStratagem == Compound::Match_Exact) 
00731         {
00732             // low tolerance breaks planarity just about everywhere
00733             matchDefaultAtomChirality(atomTargets, 0.01, false);
00734 
00735             matchDefaultBondLengths(atomTargets);
00736             matchDefaultBondAngles(atomTargets);
00737             
00738             // Set dihedral angles even when bonded atoms are planar
00739             matchDefaultDihedralAngles(atomTargets, Compound::DistortPlanarBonds);
00740 
00741             matchDefaultTopLevelTransform(atomTargets);
00742             
00743             // No further optimization should be needed
00744             
00745             return *this;
00746         }
00747         
00748         else if (matchStratagem == Compound::Match_Idealized) 
00749         {
00750             // Break planarity constraint only when input atoms are 90 degrees out of plane
00751             matchDefaultAtomChirality(atomTargets, 90*Deg2Rad, true);
00752             
00753             // Avoid setting non zero/180 dihedral angles on bonded planar atoms
00754             matchDefaultDihedralAngles(atomTargets, Compound::FlipPlanarBonds);
00755             
00756             matchDefaultTopLevelTransform(atomTargets);
00757 
00758             // At this point the structure match is approximate and may have
00759             // many bad contacts.  Optimization is needed
00760             // TODO - ObservedPointFitter on internal coordinates
00761             fitDefaultConfiguration(atomTargets, 0.005);
00762             
00763             return *this;
00764         }
00765             
00766         else assert(false); // unknown match stratagem
00767 
00768         return *this;
00769     }
00770 
00772     Compound& fitDefaultConfiguration(
00773             const AtomTargetLocations& atomTargets,
00774             SimTK::Real targetRms);
00775     
00777     const Compound& populateDefaultPdbChain(
00778         class PdbChain&, 
00779         int& defaultNextResidueNumber,
00780         const Transform& transform = Transform()) const;
00781 
00783     const Compound& populatePdbChain(
00784         const State& state, 
00785         class PdbChain&, 
00786         int& defaultNextResidueNumber,
00787         const Transform& transform = Transform()) const;
00788 
00794     std::ostream& writeDefaultPdb(
00795         std::ostream& os, 
00796         const Transform& transform = Transform()  
00797         ) const;
00798 
00804     void writeDefaultPdb(
00805         const char* outFileName, 
00806         const Transform& transform
00807         ) const;
00808 
00816     std::ostream& writeDefaultPdb(
00817         std::ostream& os, 
00818         int& nextAtomSerialNumber, 
00819         const Transform& transform = Transform() 
00820         ) const;
00821 
00827     std::ostream& writePdb(
00828         const State& state, 
00829         std::ostream& os,  
00830         const Transform& transform = Transform() 
00831         ) const;
00832 
00833 
00841     std::ostream& writePdb(
00842         const State& state, 
00843         std::ostream& os,  
00844         int& nextAtomSerialNumber,  
00845         const Transform& transform = Transform() 
00846         ) const;
00847 
00849     // end configuration section
00850 
00851 
00854 
00864     Compound& setCompoundName(const Name& 
00865         );
00866 
00867 
00869     const Name& getCompoundName() const;
00870 
00879     Compound& addCompoundSynonym(const Name& 
00880         );
00881 
00886     const AtomPathName getAtomName(Compound::AtomIndex 
00887         ) const;
00888 
00890     const Element& getAtomElement(Compound::AtomIndex 
00891         ) const;
00892 
00893     const Element& getAtomElement(const Compound::AtomName& 
00894         ) const;
00895 
00899     Compound& nameAtom(
00900         const Compound::AtomName& newName, 
00901         const AtomPathName& oldName 
00902         );
00903 
00907     Compound& nameAtom(
00908         const Compound::AtomName& newName,  
00909         const AtomPathName& oldName,  
00910         BiotypeIndex biotype 
00911         );
00912 
00923     Compound& defineDihedralAngle(
00924         const Compound::DihedralName& angleName, 
00925         const Compound::AtomPathName& atom1, 
00926         const Compound::AtomPathName& atom2, 
00927         const Compound::AtomPathName& atom3, 
00928         const Compound::AtomPathName& atom4, 
00929         Angle offset = 0*Deg2Rad 
00930         );
00931 
00946     Compound& defineDihedralAngle(
00947         const Compound::DihedralName& angleName, 
00948         const Compound::BondCenterPathName& bond1, 
00949         const Compound::BondCenterPathName& bond2, 
00950         Angle offset = 0*Deg2Rad 
00951         );
00952 
00958     Compound& setPdbResidueNumber(int resNum);
00959 
00961     int getPdbResidueNumber() const;
00962 
00968     Compound& setPdbResidueName(const String& resName);
00969 
00971     const String& getPdbResidueName() const;
00972 
00978     Compound& setPdbChainId(char chainId 
00979         );
00980 
00982     char getPdbChainId() const;
00983 
00989     Compound& nameBondCenter(
00990         const Compound::BondCenterName& newName, 
00991         const BondCenterPathName& oldName 
00992         );
00993 
00999     Compound& inheritAtomNames(const Compound::Name& 
01000         );
01001     
01002     Compound& inheritCompoundSynonyms(const Compound& otherCompound);
01003     
01009     Compound& inheritBondCenterNames(const Compound::Name& 
01010         );
01011 
01013     Compound::AtomIndex getAtomIndex(const Compound::AtomPathName& 
01014         ) const;
01015 
01017     // end nomenclature methods
01018 
01019 
01022 
01028     //void setCompoundSystem(CompoundSystem& system, ///< The CompoundSystem that will take ownership of this Compound.
01029     //                       Compound::Index);       ///< The index within the new owner CompoundSystem that this Compound will have.
01030 
01031     void setMultibodySystem(MultibodySystem& system);
01032 
01038     Compound& setBondMobility(
01039         BondMobility::Mobility mobility, 
01040         const AtomPathName& atom1, 
01041         const AtomPathName& atom2 
01042         );
01043 
01049     Compound& setBondMobility(
01050         BondMobility::Mobility mobility,  
01051         Compound::BondIndex bondIndex 
01052         );
01053 
01061     Compound  & setCompoundBondMobility(BondMobility::Mobility mobility);
01062 
01070     MobilizedBodyIndex getAtomMobilizedBodyIndex(Compound::AtomIndex 
01071         ) const;
01072 
01080     Vec3 getAtomLocationInMobilizedBodyFrame(Compound::AtomIndex 
01081         ) const;
01082 
01088     Compound& setBiotypeIndex(
01089         const Compound::AtomPathName& atomName, 
01090         BiotypeIndex biotype 
01091         );
01092     
01093     Compound& setAtomBiotype(
01094             const Compound::AtomPathName& atomName,
01095             const String& biotypeResidueName,
01096             const String& biotypeAtomName,
01097             SimTK::Ordinality::Residue ordinality = SimTK::Ordinality::Any
01098             )
01099     {
01100         Compound::AtomIndex atomIndex = getAtomIndex(atomName);
01101         
01102         if ( ! Biotype::exists(biotypeResidueName, biotypeAtomName, ordinality) )
01103             Biotype::defineBiotype(
01104                 getAtomElement(atomIndex),
01105                 getNumBondCenters(atomIndex), 
01106                 biotypeResidueName, 
01107                 biotypeAtomName, 
01108                 ordinality
01109             );
01110         
01111         const Biotype& biotype = Biotype::get(biotypeResidueName, biotypeAtomName, ordinality);
01112         
01113         assert( biotype.getElement() == getAtomElement(atomIndex) );
01114         assert( biotype.getValence() == getNumBondCenters(atomIndex) );
01115         
01116         BiotypeIndex biotypeIndex = biotype.getIndex();
01117         setBiotypeIndex(atomName, biotypeIndex);
01118 
01119         return *this;
01120     }
01121 
01123     BiotypeIndex getAtomBiotypeIndex(Compound::AtomIndex 
01124         ) const;
01125 
01126     // RUNTIME INTERFACE
01127 
01135     DuMM::AtomIndex getDuMMAtomIndex(Compound::AtomIndex) const;
01136 
01138     // end simulation methods
01139 
01141     Compound& setTopLevelTransform(const Transform& transform);
01142 
01144     const Transform& getTopLevelTransform() const;
01145 
01146 
01147 
01148 protected:
01149 
01153     void setDuMMAtomIndex(
01154         Compound::AtomIndex, 
01155         DuMM::AtomIndex 
01156         );
01157 
01158     explicit Compound(CompoundRep* ip);
01159     friend class CompoundSystem;
01160 
01161 private:
01162     // OBSOLETE: use getNumAtoms()
01163     int getNAtoms() const {return getNumAtoms();}
01164     // OBSOLETE: use getNumBondCenters()
01165     size_t getNBondCenters() const {return getNumBondCenters();}
01166     // OBSOLETE: use getNumBondCenters()
01167     size_t getNBondCenters(Compound::AtomIndex atomIndex) const {return getNumBondCenters(atomIndex);}
01168     // OBSOLETE: use getNumBonds()
01169     size_t getNBonds() const {return getNumBonds();}
01170 };
01171 
01172 
01180 SimTK_MOLMODEL_EXPORT std::ostream& operator<<(std::ostream& o, const Compound& c);
01181 
01191 class  Compound::SingleAtom : public Compound {
01192 public:
01193     SingleAtom(
01194         const Compound::AtomName& atomName, 
01195         const Element& element 
01196         ) 
01197     {
01198         setBaseAtom( atomName, element );
01199 
01200         setCompoundName("SingleAtom"); // should be overridden by derived class constructors
01201     }
01202 };
01203 
01204 
01219 class  UnivalentAtom : public Compound::SingleAtom {
01220 public:
01221     UnivalentAtom(
01222         const Compound::AtomName& atomName, 
01223         const Element& element 
01224         ) 
01225         : Compound::SingleAtom(atomName, element)
01226     {
01227         addFirstBondCenter( "bond", atomName);
01228         setInboardBondCenter("bond");
01229 
01230         setCompoundName("UnivalentAtom"); // should be overridden by derived class constructors
01231     }
01232 };
01233 
01234 
01240 class  BivalentAtom : public Compound::SingleAtom {
01241 public:
01242     BivalentAtom(
01243         const Compound::AtomName& atomName,  
01244         const Element& element,  
01245         Angle angle = 180*Deg2Rad 
01246         ) 
01247         : Compound::SingleAtom(atomName, element)
01248     {        
01249         // BondCenter1 dihedral will be relative to BondCenter2
01250         addFirstBondCenter( "bond1", atomName);
01251         // conversely, bond center 2 dihedral is relative to bond center 1
01252         addSecondBondCenter( "bond2", atomName, angle);
01253         setInboardBondCenter("bond1"); // without loss of generality
01254 
01255         setCompoundName("BivalentAtom"); // should be overridden by derived class constructors
01256     }
01257 };
01258 
01259 
01266 class  TrivalentAtom : public Compound::SingleAtom {
01267 public:
01268     TrivalentAtom(
01269         const Compound::AtomName& atomName,   
01270         const Element& element,   
01271         Angle angle1 = 120*Deg2Rad, 
01272         Angle angle2 = 120*Deg2Rad 
01273         ) 
01274         : Compound::SingleAtom(atomName, element)
01275     {
01276         // BondCenter1 dihedral will be relative to BondCenter2
01277         addFirstBondCenter( "bond1", atomName );
01278         // bond centers 2 and 3 dihedrals relative to bond center 1
01279         addSecondBondCenter( "bond2", atomName,  angle1);
01280         addPlanarBondCenter( "bond3", atomName, angle2, 360*Deg2Rad - angle1 - angle2);
01281 
01282         // Choice of inboard bond may differ from bond priority - user may change this
01283         setInboardBondCenter("bond1");
01284 
01285         setCompoundName("TrivalentAtom"); // should be overridden by derived class constructors
01286     }
01287 };
01288 
01294 class  QuadrivalentAtom : public Compound::SingleAtom {
01295 public:
01296     QuadrivalentAtom(
01297         const Compound::AtomName& atomName, 
01298         const Element& element 
01299         ) 
01300         : Compound::SingleAtom(atomName, element)
01301     {
01302         static const Angle TetrahedralAngle = 109.47 * Deg2Rad;
01303 
01304         // BondCenter1 dihedral will be relative to BondCenter2
01305         // Using Rotation() constructor that takes x axis and approximate y axis
01306         addFirstBondCenter( "bond1", atomName );
01307         // bond centers 2, 3, and 4 dihedrals will be relative to bond1
01308         addSecondBondCenter( "bond2", atomName, TetrahedralAngle );
01309         addLeftHandedBondCenter( "bond3", atomName, TetrahedralAngle, TetrahedralAngle );
01310         addRightHandedBondCenter( "bond4", atomName, TetrahedralAngle, TetrahedralAngle );
01311 
01312         // Choice of inboard bond may differ from bond priority - user may change this
01313         setInboardBondCenter("bond1");
01314 
01315         // default dihedral should be left blank, so it could be
01316         // defined from the other side.
01317         // the ultimate default will be 180 degrees anyway.
01318         // setDefaultInboardDihedralAngle(180*Deg2Rad);
01319 
01320         setCompoundName("QuadrivalentAtom"); // should be overridden by derived class constructors
01321     }
01322         
01323     QuadrivalentAtom(
01324         const Compound::AtomName& atomName, 
01325         const Element& element, 
01326         Angle bond12Angle, 
01327         Angle bond13Angle, 
01328         Angle bond14Angle, 
01329         Angle dihedral3, 
01330         Angle dihedral4 
01331         ) 
01332         : Compound::SingleAtom(atomName, element)
01333     {
01334         // BondCenter1 dihedral will be relative to BondCenter2
01335         // Using Rotation() constructor that takes x axis and approximate y axis
01336         addFirstBondCenter( "bond1", atomName );
01337         // bond centers 2, 3, and 4 dihedrals will be relative to bond1
01338         addSecondBondCenter( "bond2", atomName, bond12Angle );
01339         
01340         // Compute bond23Angle and bond24Angle
01341         SimTK::Vec3 v1(0,0,1);
01342         SimTK::Vec3 v2 = SimTK::Rotation(bond12Angle, ZAxis) * SimTK::Vec3(0,0,1);
01343         SimTK::Vec3 v3 = SimTK::Rotation(dihedral3, YAxis) * SimTK::Rotation(bond12Angle, ZAxis) * SimTK::Vec3(0,0,1);
01344         SimTK::Vec3 v4 = SimTK::Rotation(dihedral4, YAxis) * SimTK::Rotation(bond12Angle, ZAxis) * SimTK::Vec3(0,0,1);
01345         
01346         Angle bond23Angle = std::acos(SimTK::dot(v2, v3));
01347         Angle bond24Angle = std::acos(SimTK::dot(v2, v4));
01348         
01349         // restrict angle range to (-Pi,Pi)
01350         while (dihedral3 >   Pi) dihedral3 -= 2.0*Pi;
01351         while (dihedral3 <= -Pi) dihedral3 += 2.0*Pi;
01352         while (dihedral4 >   Pi) dihedral4 -= 2.0*Pi;
01353         while (dihedral4 <= -Pi) dihedral4 += 2.0*Pi;
01354         
01355         if (dihedral3 > 0)
01356             addLeftHandedBondCenter( "bond3", atomName, bond13Angle, bond23Angle );
01357         else
01358             addRightHandedBondCenter( "bond3", atomName, bond13Angle, bond23Angle );
01359         
01360         if (dihedral4 > 0)
01361             addLeftHandedBondCenter( "bond4", atomName, bond14Angle, bond24Angle );
01362         else 
01363             addRightHandedBondCenter( "bond4", atomName, bond14Angle, bond24Angle );
01364 
01365         // Choice of inboard bond may differ from bond priority - user may change this
01366         setInboardBondCenter("bond1");
01367 
01368         // default dihedral should be left blank, so it could be
01369         // defined from the other side.
01370         // the ultimate default will be 180 degrees anyway.
01371         // setDefaultInboardDihedralAngle(180*Deg2Rad);
01372 
01373         setCompoundName("QuadrivalentAtom"); // should be overridden by derived class constructors
01374     }
01375 };
01376 
01377 
01381 class  AliphaticHydrogen : public UnivalentAtom {
01382 public:
01383     explicit AliphaticHydrogen(const AtomName& atomName = "H" 
01384         ) 
01385         : UnivalentAtom(atomName, Element::Hydrogen())
01386     {
01387         setDefaultInboardBondLength(0.1112); // for bonding to aliphatic carbon
01388 
01389         setCompoundName("AliphaticHydrogenAtom");
01390     }
01391 };
01392 
01393 
01399 class  AliphaticCarbon : public QuadrivalentAtom {
01400 public:
01401     explicit AliphaticCarbon(const AtomName& atomName = "C" 
01402         ) 
01403         : QuadrivalentAtom(atomName, Element::Carbon()) 
01404     {
01405         // In case this bonds to another aliphatic carbon
01406         setDefaultInboardBondLength(0.15620); // for bonding to another aliphatic carbon
01407 
01408         setCompoundName("AliphaticCarbon");
01409     }
01410 };
01411 
01412 
01416 class  MethyleneGroup : public Compound {
01417 public:
01418     MethyleneGroup() {
01419         static const mdunits::Length C_Hdistance = 0.1112; // nanometers
01420 
01421         setBaseAtom(AliphaticCarbon("C"));
01422         bondAtom(AliphaticHydrogen("H1"), "C/bond3");
01423         bondAtom(AliphaticHydrogen("H2"), "C/bond4");
01424         nameBondCenter("bond1", "C/bond1");
01425         nameBondCenter("bond2", "C/bond2");
01426 
01427         setDefaultInboardBondLength(0.15620); // for bonding to another aliphatic carbon
01428 
01429         setCompoundName("MethyleneGroup");
01430     }
01431 };
01432 
01433 
01437 class  MethylGroup : public Compound {
01438 public:
01439     MethylGroup() {
01440         setBaseAtom(AliphaticCarbon("C"));
01441         bondAtom(AliphaticHydrogen("H1"), "C/bond2");
01442         bondAtom(AliphaticHydrogen("H2"), "C/bond3");
01443         bondAtom(AliphaticHydrogen("H3"), "C/bond4");
01444         nameBondCenter("bond", "C/bond1");
01445 
01446         setDefaultInboardBondLength(0.15620); // for bonding to another aliphatic carbon
01447         setCompoundName("MethylGroup");
01448     }
01449 };
01450 
01457 class  AromaticSixMemberedCHGroup : public Compound {
01458 public:
01459     AromaticSixMemberedCHGroup() {
01460         static const mdunits::Length C_Hdistance = 0.1080; // in nanometers, from tinker amber99.dat
01461         static const mdunits::Length C_Cdistance = 0.1400; // in nanometers, from tinker amber99.dat
01462 
01463         setBaseAtom( TrivalentAtom("C", Element::Carbon(), 120*Deg2Rad, 120*Deg2Rad) );
01464         bondAtom( UnivalentAtom("H", Element::Hydrogen()), "C/bond3", C_Hdistance);
01465 
01466         // remember to change default length for bonding other other things
01467         setDefaultInboardBondLength(C_Cdistance); // for bonding to other aromatic CH
01468 
01469         setCompoundName("AromaticSixMemberedCHGroup");
01470     }
01471 };
01472 
01473 
01477 class  AlcoholOHGroup : public Compound {
01478 public:
01479     AlcoholOHGroup() {
01480         static const mdunits::Length O_Hdistance = 0.0960; // nanometers
01481 
01482         setBaseAtom( BivalentAtom("O", Element::Oxygen(), 108.50 * Deg2Rad) );
01483 
01484         bondAtom( UnivalentAtom("H", Element::Hydrogen()), "O/bond2", O_Hdistance );
01485         nameBondCenter("bond", "O/bond1");
01486 
01487         // In case of bonding to aliphatic carbon
01488         setDefaultInboardBondLength(0.1410); // for bonding to aliphatic carbon
01489 
01490         setCompoundName("AlcoholOHGroup");
01491     }
01492 };
01493 
01494 
01498 class  PrimaryAmineGroup : public Compound {
01499 public:
01500     PrimaryAmineGroup() {
01501         static const mdunits::Length H_Ndistance = 0.1010; // nanometers
01502         static const mdunits::Length N_Cdistance = 0.1471; // in nanometers, for bonding to aliphatic carbon
01503 
01504         setBaseAtom( QuadrivalentAtom("N", Element::Nitrogen()) );
01505         bondAtom( UnivalentAtom("H1", Element::Hydrogen()), "N/bond2", H_Ndistance);
01506         bondAtom( UnivalentAtom("H2", Element::Hydrogen()), "N/bond3", H_Ndistance);
01507         bondAtom( UnivalentAtom("H3", Element::Hydrogen()), "N/bond4", H_Ndistance);
01508 
01509         setDefaultInboardBondLength(N_Cdistance); // for bonding to aliphatic carbon
01510     }
01511 };
01512 
01513 
01517 class  CarboxylateGroup : public Compound {
01518 public:
01519     CarboxylateGroup() {
01520         // parameters from Tinker amber99.param
01521         static const mdunits::Length O_Cdistance = 0.1250; // nanometers
01522         static const mdunits::Length C_CtDistance = 0.15220; // nanometers
01523         static const Angle O_C_Oangle = 126*Deg2Rad;
01524 
01525         // we actually use the inboard-C-O angle during construction
01526         static const Angle O_C_CtAngle = 180*Deg2Rad - 0.5*O_C_Oangle;
01527 
01528         setBaseAtom( TrivalentAtom("C", Element::Carbon(), O_C_CtAngle, O_C_CtAngle) );
01529         bondAtom( UnivalentAtom("O1", Element::Oxygen()), "C/bond2", O_Cdistance);
01530         bondAtom( UnivalentAtom("O2", Element::Oxygen()), "C/bond3", O_Cdistance);
01531 
01532         setDefaultInboardBondLength(C_CtDistance);
01533 
01534         nameBondCenter("bond", "C/bond1");
01535     }
01536 };
01537 
01549 class  SimTK_MOLMODEL_EXPORT Molecule : public Compound {
01550 public:
01551     Molecule();
01552     SimTK_INSERT_DERIVED_HANDLE_DECLARATIONS(Molecule, CompoundRep, Compound);
01553 protected:
01554     explicit Molecule(CompoundRep* rep);
01555 };
01556 
01557 
01561 class  Argon : public Molecule {
01562 public:
01563     Argon() {
01564         setPdbResidueName("AR ");
01565 
01566         setBaseAtom( "Ar", Biotype::Argon() );
01567 
01568         setCompoundName("Argon");
01569     }
01570 };
01571 
01572 
01576 class  Methane : public Molecule {
01577 public:
01578     Methane() 
01579     {
01580         setBaseCompound("methyl", MethylGroup());
01581         inheritAtomNames("methyl");
01582 
01583         // Ordinarily, methyl group bonds to aliphatic carbon,
01584         // and has a default bond length to match.
01585         // Here we turn off the methyl inboard bond, so the
01586         // AliphaticHydrogen will, as desired, dictate the bond length
01587         convertInboardBondCenterToOutboard();
01588 
01589         bondAtom(AliphaticHydrogen("H4"), "methyl/bond", 0.1112);
01590 
01591         setBiotypeIndex( "C", Biotype::MethaneC().getIndex() );
01592         setBiotypeIndex( "H1", Biotype::MethaneH().getIndex() );
01593         setBiotypeIndex( "H2", Biotype::MethaneH().getIndex() );
01594         setBiotypeIndex( "H3", Biotype::MethaneH().getIndex() );
01595         setBiotypeIndex( "H4", Biotype::MethaneH().getIndex() );
01596 
01597         setCompoundName("Methane");
01598 
01599 
01600     }
01601 };
01602 
01606 class  Ethane : public Molecule {
01607 public:
01608     Ethane() 
01609     {
01610         setPdbResidueName("EHN");
01611 
01612         setBaseCompound("methyl1", MethylGroup());
01613         nameAtom("C1", "methyl1/C", Biotype::EthaneC().getIndex() );
01614         nameAtom("H1", "methyl1/H1", Biotype::EthaneH().getIndex() );
01615         nameAtom("H2", "methyl1/H2", Biotype::EthaneH().getIndex() );
01616         nameAtom("H3", "methyl1/H3", Biotype::EthaneH().getIndex() );
01617 
01618         // This first methyl is a base, not a decoration
01619         convertInboardBondCenterToOutboard();
01620 
01621         bondCompound("methyl2", MethylGroup(), "methyl1/bond");
01622 
01623         nameAtom("C2", "methyl2/C", Biotype::EthaneC().getIndex() );
01624         nameAtom("H4", "methyl2/H1", Biotype::EthaneH().getIndex() );
01625         nameAtom("H5", "methyl2/H2", Biotype::EthaneH().getIndex() );
01626         nameAtom("H6", "methyl2/H3", Biotype::EthaneH().getIndex() );
01627 
01628         defineDihedralAngle("torsion", "H1", "C1", "C2", "H4");
01629 
01630         setDefaultTorsionAngle(180*Deg2Rad);
01631         // setBondRotatable(false, "C1", "C2");
01632 
01633         setCompoundName("Ethane");
01634 
01635     }
01636 
01642     Ethane& setDefaultTorsionAngle(Angle angle 
01643         ) {
01644         setDefaultDihedralAngle("torsion", angle);
01645 
01646         return *this;
01647     }
01648 
01652     Angle calcDefaultTorsionAngle() const {
01653         return calcDefaultDihedralAngle("torsion");
01654     }
01655 };
01656 
01663 class BiopolymerResidueRep;
01664 // class SimTK_MOLMODEL_EXPORT BiopolymerResidue : public Compound {
01665 class SimTK_MOLMODEL_EXPORT BiopolymerResidue : public Compound {
01666 public:   
01670     BiopolymerResidue(
01671         const Compound::Name& residueTypeName, 
01672         const String& threeLetterCode, 
01673         char oneLetterCode 
01674         );
01675 
01679     BiopolymerResidue& setOneLetterCode(char olc 
01680         );
01681 
01685     BiopolymerResidue& setThreeLetterCode(const String& tlc 
01686         );
01687 
01691     BiopolymerResidue& setResidueTypeName(const String& name 
01692         );
01693     
01694     char getOneLetterCode() const;
01695     const String& getThreeLetterCode() const;
01696     const String& getResidueTypeName() const;
01697 
01707     bool assignBiotypes(
01708         Ordinality::Residue ordinality = Ordinality::Any 
01709         );
01710 
01711     Compound::AtomIndex getParentCompoundAtomIndex(AtomIndex residueAtomIndex) const;
01712 
01713     SimTK_INSERT_DERIVED_HANDLE_DECLARATIONS(BiopolymerResidue,BiopolymerResidueRep,Compound);
01714 };
01715 
01716 class BiopolymerRep;
01717 
01718 // This class to point to residue atoms in a Biopolymer
01719 class ResidueInfo {
01720 public:
01724     SimTK_DEFINE_UNIQUE_LOCAL_INDEX_TYPE(ResidueInfo,Index);
01725     SimTK_DEFINE_UNIQUE_LOCAL_INDEX_TYPE(ResidueInfo,AtomIndex);
01726 
01727     class AtomInfo {
01728     public:
01729         friend class ResidueInfo;
01730 
01731         AtomInfo(Compound::AtomIndex index, const Compound::AtomName& name) 
01732             : pdbAtomName(name), biopolymerAtomIndex(index)
01733         {
01734             synonyms.insert(name);
01735         }
01736 
01737         const std::set<Compound::AtomName>& getNames() const {
01738             return synonyms;
01739         }
01740 
01741     private:
01742         Compound::AtomIndex biopolymerAtomIndex;
01743         String pdbAtomName;
01744         std::set<Compound::AtomName> synonyms;
01745     };
01746 
01747 
01748     ResidueInfo(
01749         ResidueInfo::Index ix, 
01750         const Compound::Name& name, 
01751         const BiopolymerResidue& res,
01752         Compound::AtomIndex atomOffset,
01753         char insertionCode = ' ');
01754 
01755     AtomIndex addAtom(Compound::AtomIndex index, const Compound::AtomName& name) {
01756         ResidueInfo::AtomIndex answer(atoms.size());
01757         atoms.push_back(AtomInfo(index, name));
01758         atomIdsByName[name] = answer;
01759         return answer;
01760     }
01761 
01762     size_t getNumAtoms() const {
01763         return atoms.size();
01764     }
01765 
01766     const AtomInfo& getAtomInfo(AtomIndex a) const {
01767         return atoms[a];
01768     }
01769     AtomInfo& updAtomInfo(AtomIndex a) {
01770         return atoms[a];
01771     }
01772 
01773     const std::set<Compound::Name>& getNames() const {return synonyms;}
01774 
01775     const Compound::Name& getPdbResidueName() const {
01776         return pdbResidueName;
01777     }
01778 
01779     const int getPdbResidueNumber() const {
01780         return pdbResidueNumber;
01781     }
01782 
01783     const char getPdbInsertionCode() const {
01784         return pdbInsertionCode;
01785     }
01786 
01787     Compound::AtomIndex getAtomIndex(ResidueInfo::AtomIndex a) const {
01788         return atoms[a].biopolymerAtomIndex;
01789     }
01790 
01791     Compound::AtomIndex getAtomIndex(Compound::AtomName a) const {
01792         return atoms[atomIdsByName.find(a)->second].biopolymerAtomIndex;
01793     }
01794 
01795     const String& getAtomName(ResidueInfo::AtomIndex a) const {
01796         return atoms[a].pdbAtomName;
01797     }
01798 
01799     const std::set<Compound::AtomName>& getAtomSynonyms(ResidueInfo::AtomIndex a) const {
01800         return atoms[a].synonyms;
01801     }
01802 
01803     const Compound::Name& getName() const {return nameInCompound;}
01804 
01805     ResidueInfo& setPdbResidueNumber(int num) {
01806         pdbResidueNumber = num;
01807         return *this;
01808     }
01809 
01810     ResidueInfo::Index getIndex() const {return index;}
01811 
01812 private:
01813     ResidueInfo::Index index;
01814     Compound::Name nameInCompound;
01815     Compound::Name pdbResidueName;
01816     std::set<Compound::Name> synonyms;
01817     int pdbResidueNumber;
01818     char pdbInsertionCode;
01819     std::vector<AtomInfo> atoms;
01820     std::map<const Compound::Name, AtomIndex> atomIdsByName;
01821     // TODO - put private data in ResidueInfoRep
01822 };
01823 
01832 class SimTK_MOLMODEL_EXPORT Biopolymer : public Molecule
01833 {
01834 public:
01838     typedef String Sequence;
01839     
01843     Biopolymer();
01844 
01848     int getNumResidues() const;
01849 
01855     const ResidueInfo& getResidue(
01856         ResidueInfo::Index residueIndex 
01857         ) const;
01858 
01864     ResidueInfo& updResidue(
01865         ResidueInfo::Index residueIndex 
01866         ); 
01867 
01871     const ResidueInfo& getResidue(
01872         Compound::Name residueName 
01873         ) const;
01874 
01878     ResidueInfo& updResidue(
01879         Compound::Name residueName 
01880         );
01881 
01887     const Compound::Name& getResidueName(
01888         ResidueInfo::Index residueIndex 
01889         ) const;
01890 
01891     // BiopolymerResidue createResidueCompound(ResidueInfo::Index r) const;
01892 
01899     Biopolymer& renumberPdbResidues(int firstPdbResidueNumber); 
01900     
01901     bool assignResidueBiotypes(ResidueInfo::Index, Ordinality::Residue);
01902 
01910     void assignBiotypes();
01911 
01915     ResidueInfo::Index appendResidue(
01916         const Compound::Name& resName, 
01917         const BiopolymerResidue& residue 
01918         );
01919 
01923     ResidueInfo::Index appendResidue(
01924         const Compound::Name& resName, 
01925         const BiopolymerResidue& residue, 
01926         BondMobility::Mobility mobility 
01927         );
01928 
01929     Biopolymer& setResidueBondMobility(ResidueInfo::Index, BondMobility::Mobility);
01930     MobilizedBodyIndex getResidueAtomMobilizedBodyIndex(ResidueInfo::Index res, ResidueInfo::AtomIndex a) const {
01931         return getAtomMobilizedBodyIndex(getResidue(res).getAtomIndex(a));
01932     }
01933     Vec3 getResidueAtomLocationInMobilizedBodyFrame(ResidueInfo::Index res, ResidueInfo::AtomIndex a) const {
01934         return getAtomLocationInMobilizedBodyFrame(getResidue(res).getAtomIndex(a));
01935     }
01936 
01937     virtual AtomTargetLocations createAtomTargets(const class PdbStructure& targetStructure) const;
01938     virtual AtomTargetLocations createAtomTargets(const class PdbChain& targetChain) const;
01939 
01940     SimTK_INSERT_DERIVED_HANDLE_DECLARATIONS(Biopolymer, BiopolymerRep, Molecule);
01941 
01942     // OBSOLETE; TODO: remove in SimTK 2.0
01943     int getNResidues() const {return getNumResidues();}
01944 
01945 private:
01946 };
01947 
01948 
01949 } // namespace SimTK
01950 
01951 #endif // SimTK_MOLMODEL_COMPOUND_H_
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines