00001 #ifndef MOLMODEL_PDB_H_
00002 #define MOLMODEL_PDB_H_
00003
00004 #include "SimTKsimbody.h"
00005 #include <cctype>
00006 #include "molmodel/internal/Compound.h"
00007 #include <map>
00008
00009 namespace SimTK {
00010
00011 namespace Pdb {
00012 SimTK_DEFINE_UNIQUE_INDEX_TYPE(AtomIndex);
00013 SimTK_DEFINE_UNIQUE_INDEX_TYPE(ResidueIndex);
00014 SimTK_DEFINE_UNIQUE_INDEX_TYPE(ChainIndex);
00015 SimTK_DEFINE_UNIQUE_INDEX_TYPE(ModelIndex);
00016 }
00017
00020 class SimTK_MOLMODEL_EXPORT PdbResidueId {
00021 public:
00022 explicit PdbResidueId(int num, char iCode = ' ') : residueNumber(num), insertionCode(iCode) {}
00023
00025 bool operator<(const PdbResidueId& other) const;
00026
00027 int residueNumber;
00028 char insertionCode;
00029 };
00030
00031 namespace Exception
00032 {
00033 class UndefinedPdbChainId : public Exception::Base
00034 {
00035 public:
00036 UndefinedPdbChainId(const char* fn, int ln, char chainId)
00037 : Exception::Base(fn, ln)
00038 {
00039 String chainString = " ";
00040 chainString[0] = chainId;
00041 setMessage("Undefined PDB chain Id: '" + chainString + "'");
00042 }
00043
00044 };
00045
00046 class DuplicatePdbResidue : public Exception::Base
00047 {
00048 public:
00049 DuplicatePdbResidue(const char* fn, int ln, PdbResidueId pdbResidueId)
00050 : Exception::Base(fn, ln)
00051 {
00052 String message("Duplicate PDB Residue number ");
00053 message += String(pdbResidueId.residueNumber);
00054
00055 setMessage(message);
00056 }
00057
00058 };
00059
00060 class UndefinedAminoAcidResidue : public Exception::Base
00061 {
00062 public:
00063 UndefinedAminoAcidResidue(const char* fn, int ln, String residueName)
00064 : Exception::Base(fn, ln)
00065 {
00066 String message("Unknown amino acid residue name '");
00067 message += residueName;
00068 message += "'";
00069
00070 setMessage(message);
00071 }
00072
00073 };
00074 }
00075
00077 class SimTK_MOLMODEL_EXPORT PdbAtomLocation {
00078 public:
00079 explicit PdbAtomLocation(SimTK::Vec3 coords, char altLoc = ' ', SimTK::Real tFac = 0.00, SimTK::Real occ = 1.0)
00080 : coordinates(coords), alternateLocationIndicator(altLoc), temperatureFactor(tFac), occupancy(occ)
00081 {}
00082
00084 std::ostream& writePdb(std::ostream& os, const Transform& transform) const;
00085
00086 const Vec3& getCoordinates() const {return coordinates;}
00087
00088 char getAlternateLocationIndicator() const {return alternateLocationIndicator;}
00089
00090 SimTK::Real getTemperatureFactor() const {return temperatureFactor;}
00091
00092 SimTK::Real getOccupancy() const {return occupancy;}
00093
00094 private:
00095
00096
00097 #if defined(_MSC_VER)
00098 #pragma warning(push)
00099 #pragma warning(disable:4251)
00100 #endif
00101
00102 SimTK::Vec3 coordinates;
00103
00104 #if defined(_MSC_VER)
00105 #pragma warning(pop)
00106 #endif
00107
00108 char alternateLocationIndicator;
00109 SimTK::Real temperatureFactor;
00110 SimTK::Real occupancy;
00111 };
00112
00114 class SimTK_MOLMODEL_EXPORT PdbAtom {
00115 friend class PdbResidue;
00116 typedef std::vector<SimTK::String> AtomNameList;
00117 public:
00118 explicit PdbAtom(const SimTK::String& name, const Element& e);
00119
00120 explicit PdbAtom(
00121 const class Compound& compound,
00122 const String& atomName,
00123 const Transform& transform = Transform() );
00124
00125 explicit PdbAtom(
00126 const State& state,
00127 const class Compound& compound,
00128 const String& atomName,
00129 const Transform& transform = Transform() );
00130
00131 std::ostream& write(
00132 std::ostream& os,
00133 int& nextAtomSerialNumber,
00134 const char residueName[4],
00135 PdbResidueId residueId,
00136 char chainId,
00137 const Transform& transform) const;
00138
00139 bool hasLocation(char altLoc) const;
00140
00141 bool hasLocation() const;
00142
00143 Vec3 getLocation(char altLoc) const;
00144
00145 Vec3 getLocation() const;
00146
00147 PdbAtom& setLocation(const PdbAtomLocation& loc) {
00148 char alt_loc = loc.getAlternateLocationIndicator();
00149 if (locationIndicesById.find(alt_loc) == locationIndicesById.end()) {
00150 locationIndicesById[alt_loc] = locations.size();
00151 locations.push_back(loc);
00152 }
00153 else {
00154 locations[locationIndicesById.find(alt_loc)->second] = loc;
00155 }
00156
00157 return *this;
00158 }
00159
00160 const String& getName() const {return atomName;}
00161
00162 const PdbAtomLocation& getPdbAtomLocation() const {
00163 assert(hasLocation());
00164 return locations[0];
00165 }
00166
00167 const Vec3& getCoordinates() const {
00168 return getPdbAtomLocation().getCoordinates();
00169 }
00170
00171 char getAlternateLocationIndicator() const {
00172 return getPdbAtomLocation().getAlternateLocationIndicator();
00173 }
00174
00175 SimTK::Real getTemperatureFactor() const {
00176 return getPdbAtomLocation().getTemperatureFactor();
00177 }
00178
00179 SimTK::Real getOccupancy() const {
00180 return getPdbAtomLocation().getOccupancy();
00181 }
00182
00183
00184 protected:
00185 void parsePdbLine(const String& line);
00186
00189 static String canonicalizeAtomName(const String& casualName);
00190
00192 static std::vector<SimTK::String> generatePossibleAtomNames(SimTK::String name);
00193
00194 private:
00195 Element element;
00196
00197
00198 #if defined(_MSC_VER)
00199 #pragma warning(push)
00200 #pragma warning(disable:4251)
00201 #endif
00202
00203 SimTK::String atomName;
00204 typedef std::vector<PdbAtomLocation> Locations;
00205 Locations locations;
00206 std::map<char, int> locationIndicesById;
00207
00208 #if defined(_MSC_VER)
00209 #pragma warning(pop)
00210 #endif
00211
00212 };
00213
00215 class SimTK_MOLMODEL_EXPORT PdbResidue {
00216 friend class PdbChain;
00217 public:
00218 explicit PdbResidue(String name, PdbResidueId id);
00219
00220 explicit PdbResidue(
00221 const class Compound& compound,
00222 int residueNumber,
00223 const Transform& transform = Transform() );
00224
00225 explicit PdbResidue(
00226 const State& state,
00227 const class Compound& compound,
00228 int residueNumber,
00229 const Transform& transform = Transform() );
00230
00231 std::ostream& write(std::ostream& os, int& nextAtomSerialNumber, char chainId, const Transform& transform) const;
00232
00233 bool hasAtom(SimTK::String argName) const;
00234
00235 const PdbAtom& getAtom(String argName) const;
00236
00237 PdbAtom& updAtom(String argName);
00238
00239 const PdbResidueId& getResidueId() const {return residueId;}
00240 const char* getName() const {return residueName;}
00241 int getPdbResidueNumber() const {return residueId.residueNumber;}
00242 char getInsertionCode() const {return residueId.insertionCode;}
00243
00244 size_t getNumAtoms() const { return atoms.size(); }
00245
00246 const PdbAtom& getAtom(Pdb::AtomIndex atomIx) const {
00247 return atoms[atomIx];
00248 }
00249
00250 void addAtom(const PdbAtom& atom);
00251
00252
00253 size_t getNAtoms() const {return getNumAtoms();}
00254 protected:
00255 void parsePdbLine(const String& line);
00256
00257 private:
00258 char residueName[4];
00259 PdbResidueId residueId;
00260
00261
00262 #if defined(_MSC_VER)
00263 #pragma warning(push)
00264 #pragma warning(disable:4251)
00265 #endif
00266
00267 typedef std::vector<PdbAtom> Atoms;
00268 Atoms atoms;
00269 std::map<SimTK::String, int> atomIndicesByName;
00270
00271 #if defined(_MSC_VER)
00272 #pragma warning(pop)
00273 #endif
00274
00275 };
00276
00277 class Compound;
00278
00281 class SimTK_MOLMODEL_EXPORT PdbChain {
00282 friend class PdbModel;
00283 public:
00284 explicit PdbChain(char id = ' ') : chainId(id) {}
00285
00286 explicit PdbChain(
00287 const Compound& compound,
00288 const Transform& transform = Transform());
00289
00290 explicit PdbChain(
00291 const State& state,
00292 const Compound& compound,
00293 const Transform& transform = Transform());
00294
00295 std::ostream& write(std::ostream& os, int& nextAtomSerialNumber, const Transform& transform = Transform()) const;
00296
00297 bool hasResidue(PdbResidueId pdbResidueId) const;
00298
00299 bool hasAtom(String atomName, PdbResidueId residueId) const;
00300
00301 const PdbAtom& getAtom(String atomName, PdbResidueId residueId) const;
00302
00303 PdbAtom& updAtom(String atomName, PdbResidueId residueId);
00304
00305 PdbResidue& appendResidue( const PdbResidue& residue )
00306 {
00307 if ( residueIndicesById.find(residue.getResidueId()) != residueIndicesById.end() )
00308 SimTK_THROW1( Exception::DuplicatePdbResidue, residue.getResidueId() );
00309
00310 residues.push_back( residue );
00311 residueIndicesById[residue.getResidueId()] = residues.size() - 1;
00312
00313 return residues.back();
00314 }
00315
00316 size_t getNumResidues() const { return residues.size(); }
00317 const PdbResidue& getResidue(Pdb::ResidueIndex resIx) const {
00318 return residues[resIx];
00319 }
00320
00321 size_t getNumAtoms() const {
00322 size_t atomCount = 0;
00323 for (Pdb::ResidueIndex r(0); r < getNumResidues(); ++r) {
00324 atomCount += getResidue(r).getNumAtoms();
00325 }
00326
00327 return atomCount;
00328 }
00329
00330 char getChainId() const {return chainId;}
00331
00332
00333 size_t getNResidues() const { return getNumResidues(); }
00334
00335 size_t getNAtoms() const { return getNumAtoms(); }
00336
00337 protected:
00338 void parsePdbLine(const String& line);
00339
00340 private:
00341 char chainId;
00342
00343
00344 #if defined(_MSC_VER)
00345 #pragma warning(push)
00346 #pragma warning(disable:4251)
00347 #endif
00348
00349 typedef std::vector<PdbResidue> Residues;
00350 Residues residues;
00351 std::map<PdbResidueId, size_t> residueIndicesById;
00352
00353 #if defined(_MSC_VER)
00354 #pragma warning(pop)
00355 #endif
00356
00357 };
00358
00361 class SimTK_MOLMODEL_EXPORT PdbModel {
00362 friend class PdbStructure;
00363 public:
00364 explicit PdbModel(
00365 const Compound& compound,
00366 int number = 1,
00367 const Transform& transform = Transform());
00368
00369 explicit PdbModel(
00370 const State& state,
00371 const Compound& compound, int number = 1,
00372 const Transform& transform = Transform());
00373
00374 explicit PdbModel(int number) : modelNumber(number) {}
00375
00376 std::ostream& write(std::ostream& os, const Transform& transform) const;
00377
00378 bool hasChain(char id) const;
00379
00380 bool hasAtom(String atomName, PdbResidueId residueId, char chainId) const;
00381
00382 const PdbAtom& getAtom(String atomName, PdbResidueId residueId, char chainId) const;
00383
00384 PdbAtom& updAtom(String atomName, PdbResidueId residueId, char chainId);
00385
00386 size_t getNumChains() const {return chains.size();}
00387 const PdbChain& getChain(Pdb::ChainIndex chainIx) const {
00388 return chains[chainIx];
00389 }
00390 const PdbChain& getChain(char chainId) const;
00391
00392
00393 size_t getNChains() const {return getNumChains();}
00394
00395 protected:
00396 void parsePdbLine(const String& line);
00397
00398 PdbChain& updOrCreateChain(char chainId);
00399
00400 private:
00401 int modelNumber;
00402
00403
00404 #if defined(_MSC_VER)
00405 #pragma warning(push)
00406 #pragma warning(disable:4251)
00407 #endif
00408
00409 typedef std::vector<PdbChain> Chains;
00410 Chains chains;
00411 std::map<char, int> chainIndicesById;
00412
00413 #if defined(_MSC_VER)
00414 #pragma warning(pop)
00415 #endif
00416
00417 };
00418
00421 class SimTK_MOLMODEL_EXPORT PdbStructure {
00422 public:
00423
00425 explicit PdbStructure(
00426 const Compound& compound,
00427 const Transform& transform = Transform());
00428
00430 explicit PdbStructure(
00431 const State& state,
00432 const Compound& compound,
00433 const Transform& transform = Transform());
00434
00435 explicit PdbStructure(std::istream& pdbFile);
00436
00437 bool hasAtom(String atomName, PdbResidueId residueId, char chainId) const;
00438
00439 const PdbAtom& getAtom(String atomName, PdbResidueId residueId, char chainId) const;
00440
00441 PdbAtom& updAtom(String atomName, PdbResidueId residueId, char chainId);
00442
00443 std::ostream& write(std::ostream& os, Transform transform = Transform()) const;
00444
00445 size_t getNumModels() const {return models.size();}
00446 const PdbModel& getModel(Pdb::ModelIndex modelIx) const {
00447 return models[modelIx];
00448 }
00449
00450
00451 size_t getNModels() const {return getNumModels();}
00452 private:
00453
00454
00455 #if defined(_MSC_VER)
00456 #pragma warning(push)
00457 #pragma warning(disable:4251)
00458 #endif
00459
00460 typedef std::vector<PdbModel> Models;
00461 Models models;
00462
00463 #if defined(_MSC_VER)
00464 #pragma warning(pop)
00465 #endif
00466
00467 };
00468
00469 }
00470
00471 SimTK_MOLMODEL_EXPORT std::ostream& operator<<(std::ostream& os, const SimTK::PdbModel& pdbModel);
00472 SimTK_MOLMODEL_EXPORT std::ostream& operator<<(std::ostream& os, const SimTK::PdbStructure& pdbStructure);
00473
00474 #endif // MOLMODEL_PDB_H_