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 protected:
00253 void parsePdbLine(const String& line);
00254
00255 private:
00256 char residueName[4];
00257 PdbResidueId residueId;
00258
00259
00260 #if defined(_MSC_VER)
00261 #pragma warning(push)
00262 #pragma warning(disable:4251)
00263 #endif
00264
00265 typedef std::vector<PdbAtom> Atoms;
00266 Atoms atoms;
00267 std::map<SimTK::String, int> atomIndicesByName;
00268
00269 #if defined(_MSC_VER)
00270 #pragma warning(pop)
00271 #endif
00272
00273 private:
00274
00275 size_t getNAtoms() const {return getNumAtoms();}
00276 };
00277
00278 class Compound;
00279
00282 class SimTK_MOLMODEL_EXPORT PdbChain {
00283 friend class PdbModel;
00284 public:
00285 explicit PdbChain(char id = ' ') : chainId(id) {}
00286
00287 explicit PdbChain(
00288 const Compound& compound,
00289 const Transform& transform = Transform());
00290
00291 explicit PdbChain(
00292 const State& state,
00293 const Compound& compound,
00294 const Transform& transform = Transform());
00295
00296 std::ostream& write(std::ostream& os, int& nextAtomSerialNumber, const Transform& transform = Transform()) const;
00297
00298 bool hasResidue(PdbResidueId pdbResidueId) const;
00299
00300 bool hasAtom(String atomName, PdbResidueId residueId) const;
00301
00302 const PdbAtom& getAtom(String atomName, PdbResidueId residueId) const;
00303
00304 PdbAtom& updAtom(String atomName, PdbResidueId residueId);
00305
00306 PdbResidue& appendResidue( const PdbResidue& residue )
00307 {
00308 if ( residueIndicesById.find(residue.getResidueId()) != residueIndicesById.end() )
00309 SimTK_THROW1( Exception::DuplicatePdbResidue, residue.getResidueId() );
00310
00311 residues.push_back( residue );
00312 residueIndicesById[residue.getResidueId()] = residues.size() - 1;
00313
00314 return residues.back();
00315 }
00316
00317 size_t getNumResidues() const { return residues.size(); }
00318 const PdbResidue& getResidue(Pdb::ResidueIndex resIx) const {
00319 return residues[resIx];
00320 }
00321
00322 size_t getNumAtoms() const {
00323 size_t atomCount = 0;
00324 for (Pdb::ResidueIndex r(0); r < getNumResidues(); ++r) {
00325 atomCount += getResidue(r).getNumAtoms();
00326 }
00327
00328 return atomCount;
00329 }
00330
00331 char getChainId() const {return chainId;}
00332
00333
00334 protected:
00335 void parsePdbLine(const String& line);
00336
00337 private:
00338 char chainId;
00339
00340
00341 #if defined(_MSC_VER)
00342 #pragma warning(push)
00343 #pragma warning(disable:4251)
00344 #endif
00345
00346 typedef std::vector<PdbResidue> Residues;
00347 Residues residues;
00348 std::map<PdbResidueId, size_t> residueIndicesById;
00349
00350 #if defined(_MSC_VER)
00351 #pragma warning(pop)
00352 #endif
00353
00354 private:
00355
00356 size_t getNResidues() const { return getNumResidues(); }
00357
00358 size_t getNAtoms() const { return getNumAtoms(); }
00359 };
00360
00363 class SimTK_MOLMODEL_EXPORT PdbModel {
00364 friend class PdbStructure;
00365 public:
00366 explicit PdbModel(
00367 const Compound& compound,
00368 int number = 1,
00369 const Transform& transform = Transform());
00370
00371 explicit PdbModel(
00372 const State& state,
00373 const Compound& compound, int number = 1,
00374 const Transform& transform = Transform());
00375
00376 explicit PdbModel(int number) : modelNumber(number) {}
00377
00378 std::ostream& write(std::ostream& os, const Transform& transform) const;
00379
00380 bool hasChain(char id) const;
00381
00382 bool hasAtom(String atomName, PdbResidueId residueId, char chainId) const;
00383
00384 const PdbAtom& getAtom(String atomName, PdbResidueId residueId, char chainId) const;
00385
00386 PdbAtom& updAtom(String atomName, PdbResidueId residueId, char chainId);
00387
00388 size_t getNumChains() const {return chains.size();}
00389 const PdbChain& getChain(Pdb::ChainIndex chainIx) const {
00390 return chains[chainIx];
00391 }
00392 const PdbChain& getChain(char chainId) const;
00393
00394
00395 size_t getNChains() const {return getNumChains();}
00396
00397 protected:
00398 void parsePdbLine(const String& line);
00399
00400 PdbChain& updOrCreateChain(char chainId);
00401
00402 private:
00403 int modelNumber;
00404
00405
00406 #if defined(_MSC_VER)
00407 #pragma warning(push)
00408 #pragma warning(disable:4251)
00409 #endif
00410
00411 typedef std::vector<PdbChain> Chains;
00412 Chains chains;
00413 std::map<char, int> chainIndicesById;
00414
00415 #if defined(_MSC_VER)
00416 #pragma warning(pop)
00417 #endif
00418
00419 };
00420
00423 class SimTK_MOLMODEL_EXPORT PdbStructure {
00424 public:
00425
00427 explicit PdbStructure(
00428 const Compound& compound,
00429 const Transform& transform = Transform());
00430
00432 explicit PdbStructure(
00433 const State& state,
00434 const Compound& compound,
00435 const Transform& transform = Transform());
00436
00437 explicit PdbStructure(std::istream& pdbFile);
00438
00439 bool hasAtom(String atomName, PdbResidueId residueId, char chainId) const;
00440
00441 const PdbAtom& getAtom(String atomName, PdbResidueId residueId, char chainId) const;
00442
00443 PdbAtom& updAtom(String atomName, PdbResidueId residueId, char chainId);
00444
00445 std::ostream& write(std::ostream& os, Transform transform = Transform()) const;
00446
00447 size_t getNumModels() const {return models.size();}
00448 const PdbModel& getModel(Pdb::ModelIndex modelIx) const {
00449 return models[modelIx];
00450 }
00451
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 private:
00468
00469 size_t getNModels() const {return getNumModels();}
00470 };
00471
00472 }
00473
00474 SimTK_MOLMODEL_EXPORT std::ostream& operator<<(std::ostream& os, const SimTK::PdbModel& pdbModel);
00475 SimTK_MOLMODEL_EXPORT std::ostream& operator<<(std::ostream& os, const SimTK::PdbStructure& pdbStructure);
00476
00477 #endif // MOLMODEL_PDB_H_