00001 #ifndef SimTK_MOLMODEL_COMPOUND_H_
00002 #define SimTK_MOLMODEL_COMPOUND_H_
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
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>
00046
00047 namespace SimTK {
00048 class CompoundSystem;
00049
00050
00051 class Compound;
00052 class CompoundRep;
00053
00054
00055
00056
00057
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,
00089 Match_Idealized,
00090 Match_TopologyOnly
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
00166
00167
00173
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
00248
00250 bool hasAtom(const AtomPathName& name
00251 ) const;
00252
00254 bool hasBondCenter(const BondCenterPathName& bondCenter
00255 ) const;
00256
00258
00259
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
00509
00510
00512
00513
00514
00516 const Compound& getSubcompound(const Compound::Name& subcompoundName
00517 ) const;
00518
00520 Compound& updSubcompound(const Compound::Name& subcompoundName
00521 );
00522
00524
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};
00713 Compound& matchDefaultDihedralAngles(
00714 const AtomTargetLocations& atomTargets,
00715 PlanarBondMatchingPolicy policy = KeepPlanarBonds
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
00728 return *this;
00729
00730 else if (matchStratagem == Compound::Match_Exact)
00731 {
00732
00733 matchDefaultAtomChirality(atomTargets, 0.01, false);
00734
00735 matchDefaultBondLengths(atomTargets);
00736 matchDefaultBondAngles(atomTargets);
00737
00738
00739 matchDefaultDihedralAngles(atomTargets, Compound::DistortPlanarBonds);
00740
00741 matchDefaultTopLevelTransform(atomTargets);
00742
00743
00744
00745 return *this;
00746 }
00747
00748 else if (matchStratagem == Compound::Match_Idealized)
00749 {
00750
00751 matchDefaultAtomChirality(atomTargets, 90*Deg2Rad, true);
00752
00753
00754 matchDefaultDihedralAngles(atomTargets, Compound::KeepPlanarBonds);
00755
00756 matchDefaultTopLevelTransform(atomTargets);
00757
00758
00759
00760
00761 fitDefaultConfiguration(atomTargets, 0.005);
00762
00763 return *this;
00764 }
00765
00766 else assert(false);
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
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
01018
01019
01022
01028
01029
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
01127
01135 DuMM::AtomIndex getDuMMAtomIndex(Compound::AtomIndex) const;
01136
01138
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
01163 int getNAtoms() const {return getNumAtoms();}
01164
01165 size_t getNBondCenters() const {return getNumBondCenters();}
01166
01167 size_t getNBondCenters(Compound::AtomIndex atomIndex) const {return getNumBondCenters(atomIndex);}
01168
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");
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");
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
01250 addFirstBondCenter( "bond1", atomName);
01251
01252 addSecondBondCenter( "bond2", atomName, angle);
01253 setInboardBondCenter("bond1");
01254
01255 setCompoundName("BivalentAtom");
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
01277 addFirstBondCenter( "bond1", atomName );
01278
01279 addSecondBondCenter( "bond2", atomName, angle1);
01280 addPlanarBondCenter( "bond3", atomName, angle2, 360*Deg2Rad - angle1 - angle2);
01281
01282
01283 setInboardBondCenter("bond1");
01284
01285 setCompoundName("TrivalentAtom");
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
01305
01306 addFirstBondCenter( "bond1", atomName );
01307
01308 addSecondBondCenter( "bond2", atomName, TetrahedralAngle );
01309 addLeftHandedBondCenter( "bond3", atomName, TetrahedralAngle, TetrahedralAngle );
01310 addRightHandedBondCenter( "bond4", atomName, TetrahedralAngle, TetrahedralAngle );
01311
01312
01313 setInboardBondCenter("bond1");
01314
01315
01316
01317
01318
01319
01320 setCompoundName("QuadrivalentAtom");
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
01335
01336 addFirstBondCenter( "bond1", atomName );
01337
01338 addSecondBondCenter( "bond2", atomName, bond12Angle );
01339
01340
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
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
01366 setInboardBondCenter("bond1");
01367
01368
01369
01370
01371
01372
01373 setCompoundName("QuadrivalentAtom");
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);
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
01406 setDefaultInboardBondLength(0.15620);
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;
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);
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);
01447 setCompoundName("MethylGroup");
01448 }
01449 };
01450
01457 class AromaticSixMemberedCHGroup : public Compound {
01458 public:
01459 AromaticSixMemberedCHGroup() {
01460 static const mdunits::Length C_Hdistance = 0.1080;
01461 static const mdunits::Length C_Cdistance = 0.1400;
01462
01463 setBaseAtom( TrivalentAtom("C", Element::Carbon(), 120*Deg2Rad, 120*Deg2Rad) );
01464 bondAtom( UnivalentAtom("H", Element::Hydrogen()), "C/bond3", C_Hdistance);
01465
01466
01467 setDefaultInboardBondLength(C_Cdistance);
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;
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
01488 setDefaultInboardBondLength(0.1410);
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;
01502 static const mdunits::Length N_Cdistance = 0.1471;
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);
01510 }
01511 };
01512
01513
01517 class CarboxylateGroup : public Compound {
01518 public:
01519 CarboxylateGroup() {
01520
01521 static const mdunits::Length O_Cdistance = 0.1250;
01522 static const mdunits::Length C_CtDistance = 0.15220;
01523 static const Angle O_C_Oangle = 126*Deg2Rad;
01524
01525
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
01584
01585
01586
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
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
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
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
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
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
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
01943 int getNResidues() const {return getNumResidues();}
01944
01945 private:
01946 };
01947
01948
01949 }
01950
01951 #endif // SimTK_MOLMODEL_COMPOUND_H_