00001
00002
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 #ifndef ESBTL_PDB_H
00037 #define ESBTL_PDB_H
00038
00039 #include<boost/lexical_cast.hpp>
00040 #include <boost/algorithm/string.hpp>
00041 #include <boost/format.hpp>
00042 #include <sstream>
00043 #include <iostream>
00044 #include <typeinfo>
00045 #include <ESBTL/constants.h>
00046
00047
00048
00049 #define RECOVER_FIELD(FNAME,TYPE,FROM,TO,DEF) \
00050 TYPE get_##FNAME(const std::string& line) const { \
00051 if (line.length() < TO){\
00052 if (! Mandatory_fields::FNAME) return TYPE(DEF);\
00053 else{\
00054 std::cerr << "Fatal error: Cannot extract field \'" << #FNAME << "\' in \n";\
00055 std::cerr << "<|" << line << "|>\n";\
00056 exit (EXIT_FAILURE);\
00057 }\
00058 }\
00059 return PDB::extract_field<TYPE>(line,FROM,TO,DEF,#FNAME,Mandatory_fields::FNAME); \
00060 }
00061
00062
00063 namespace ESBTL{
00064 namespace PDB{
00066 enum Record_type{ATOM=0,HETATM,MODEL,ENDMDL,TER,END,ANISOU,CONECT,MASTER,UNKNOWN};
00067
00069 template<class T>
00070 T extract_field(const std::string& line,unsigned from, unsigned to,T default_value,const char* name,bool is_mandatory=false){
00071 std::string s=line.substr(from,to-from+1);
00072 boost::trim(s);
00073 if (s.length()==0){
00074 if (!is_mandatory)
00075 return default_value;
00076 else{
00077 std::cerr << "Fatal error: field \'"<< name << "\' is empty in \n";
00078 std::cerr << "<|" << line << "|>\n";
00079 exit (EXIT_FAILURE);
00080 }
00081 }
00082 try{
00083 return boost::lexical_cast<T>(s);
00084 }
00085 catch(boost::bad_lexical_cast &)
00086 {
00087 std::cerr << "Fatal error: Cannot convert \'"<< s << "\' to " << typeid(T).name() << " in line\n";
00088 std::cerr << "<|" << line << "|>\n";
00089 exit (EXIT_FAILURE);
00090 }
00091 }
00095 struct Mandatory_fields_default{
00096 static const bool record_name=true;
00097 static const bool atom_serial_number=true;
00098 static const bool atom_name=true;
00099 static const bool alternate_location=false;
00100 static const bool residue_name=true;
00101 static const bool chain_identifier=false;
00102 static const bool residue_sequence_number=true;
00103 static const bool insertion_code=false;
00104 static const bool x=true;
00105 static const bool y=true;
00106 static const bool z=true;
00107 static const bool occupancy=true;
00108 static const bool temperature_factor=true;
00109 static const bool element=true;
00110 static const bool charge_str=false;
00111 static const bool model_number=true;
00112 };
00113
00118
00119 template <class Mandatory_fields=Mandatory_fields_default>
00120 class Line_format{
00121 private:
00122 PDB::Record_type type;
00123
00124 public:
00125
00129 Line_format(const std::string& line){
00130 type=PDB::UNKNOWN;
00131 if (strncmp(line.c_str(),"ATOM",4)==0) type=PDB::ATOM;
00132 if (strncmp(line.c_str(),"HETATM",6)==0) type=PDB::HETATM;
00133 if (strncmp(line.c_str(),"MODEL",5)==0) type=PDB::MODEL;
00134 if (strncmp(line.c_str(),"ENDMDL",6)==0) type=PDB::ENDMDL;
00135 if (strncmp(line.c_str(),"TER",3)==0) type=PDB::TER;
00136 if (strncmp(line.c_str(),"END",3)==0) type=PDB::END;
00137 if (strncmp(line.c_str(),"ANISOU",6)==0) type=PDB::ANISOU;
00138 if (strncmp(line.c_str(),"CONECT",6)==0) type=PDB::CONECT;
00139 if (strncmp(line.c_str(),"MASTER",6)==0) type=PDB::MASTER;
00140 }
00141
00143 bool is_hetatm() const {return (type==PDB::HETATM);}
00144
00145
00146 RECOVER_FIELD(record_name,std::string,0,5," ")
00147 RECOVER_FIELD(atom_serial_number,int,6,10,-1)
00148 RECOVER_FIELD(atom_name,std::string,12,15," ")
00149 RECOVER_FIELD(alternate_location,char,16,16,' ')
00150 RECOVER_FIELD(residue_name,std::string,17,19," ")
00151 RECOVER_FIELD(chain_identifier,char,21,21,' ')
00152 RECOVER_FIELD(residue_sequence_number,int,22,25,-1)
00153 RECOVER_FIELD(insertion_code,char,26,26,' ')
00154 RECOVER_FIELD(x,double,30,37,NO_FLOAT)
00155 RECOVER_FIELD(y,double,38,45,NO_FLOAT)
00156 RECOVER_FIELD(z,double,46,53,NO_FLOAT)
00157 RECOVER_FIELD(occupancy,double,54,59,NO_FLOAT)
00158 RECOVER_FIELD(temperature_factor,double,60,65,NO_FLOAT)
00159 RECOVER_FIELD(element,std::string,76,77," ")
00161 RECOVER_FIELD(charge_str,std::string,78,79," ")
00162
00165 int get_charge(const std::string& line) const {
00166 std::string charge_str=get_charge_str(line);
00167 if (charge_str==" ")
00168 return NO_CHARGE;
00169 else{
00170 int ch=1;
00171 if (charge_str.size()==2){
00172 if (charge_str[1]=='-') ch*=-1;
00173 else{
00174 if (charge_str[1]!='+'){
00175 if (! Mandatory_fields::charge_str) return 99;
00176 std::cerr << "Fatal error: Cannot extract field \'charge\' in \n";
00177 std::cerr << "<|" << line << "|>\n";\
00178 exit(EXIT_FAILURE);
00179 }
00180 }
00181 }
00182 try{
00183 return ch*boost::lexical_cast<int>(charge_str[0]);
00184 }
00185 catch(boost::bad_lexical_cast &){
00186 if (! Mandatory_fields::charge_str) return 99;
00187 std::cerr << "Fatal error: Cannot convert \'"<< charge_str[0] << "\' to " << typeid(int).name() << " in line\n";
00188 std::cerr << "<|" << line << "|>\n";
00189 exit (EXIT_FAILURE);
00190 }
00191 }
00192 }
00193
00194
00195
00196
00197
00198 RECOVER_FIELD(model_number,int,10,13,-1)
00199
00200
00201 PDB::Record_type record_type() const{
00202 return type;
00203 }
00204
00205 };
00206
00207
00208 template<class PDB_Atom>
00209 std::string
00210 get_atom_pdb_format(const PDB_Atom& atom)
00211 {
00212 std::stringstream buf(std::stringstream::out);
00213 buf << ( !atom.is_hetatm() ? "ATOM ":"HETATM" );
00214 buf << boost::format("%5d %4s%c%3s %c%4d%c %8.3f%8.3f%8.3f%6.2f%6.2f %2s")
00215 % atom.atom_serial_number()
00216 % atom.atom_name().c_str()
00217 % atom.alternate_location()
00218 % atom.residue_name().c_str()
00219 % atom.chain_identifier()
00220 % atom.residue_sequence_number()
00221 % atom.insertion_code()
00222 % atom.x()
00223 % atom.y()
00224 % atom.z()
00225 % atom.occupancy()
00226 % atom.temperature_factor()
00227 % atom.element().c_str();
00228 if (atom.charge()==NO_CHARGE) buf << " ";
00229 else buf << boost::format("% 2i") % atom.charge();
00230 return buf.str();
00231 }
00232
00233 template<class PDB_Atom>
00234 std::string
00235 get_atom_pdb_reduced_format(const PDB_Atom& atom)
00236 {
00237 std::stringstream buf(std::stringstream::out);
00238 buf << boost::format("%5d %4s%c%3s %c%4d%c")
00239 % atom.atom_serial_number()
00240 % atom.atom_name().c_str()
00241 % atom.alternate_location()
00242 % atom.residue_name().c_str()
00243 % atom.chain_identifier()
00244 % atom.residue_sequence_number()
00245 % atom.insertion_code();
00246 return buf.str();
00247 }
00248
00249 }
00250
00251
00252 template <class Mandatory_fields>
00253 bool get_is_hetatm(const std::pair<PDB::Line_format<Mandatory_fields>,std::string>& p) {return p.first.is_hetatm(p.second);}
00254 template <class Mandatory_fields>
00255 int get_atom_serial_number(const std::pair<PDB::Line_format<Mandatory_fields>,std::string>& p) {return p.first.get_atom_serial_number(p.second) ;}
00256 template <class Mandatory_fields>
00257 std::string get_atom_name(const std::pair<PDB::Line_format<Mandatory_fields>,std::string>& p) {return p.first.get_atom_name(p.second) ;}
00258 template <class Mandatory_fields>
00259 char get_alternate_location(const std::pair<PDB::Line_format<Mandatory_fields>,std::string>& p) {return p.first.get_alternate_location(p.second) ;}
00260 template <class Mandatory_fields>
00261 double get_occupancy(const std::pair<PDB::Line_format<Mandatory_fields>,std::string>& p) {return p.first.get_occupancy(p.second) ;}
00262 template <class Mandatory_fields>
00263 double get_temperature_factor(const std::pair<PDB::Line_format<Mandatory_fields>,std::string>& p) {return p.first.get_temperature_factor(p.second) ;}
00264 template <class Mandatory_fields>
00265 std::string get_element(const std::pair<PDB::Line_format<Mandatory_fields>,std::string>& p) {return p.first.get_element(p.second) ;}
00266 template <class Mandatory_fields>
00267 int get_charge(const std::pair<PDB::Line_format<Mandatory_fields>,std::string>& p) {return p.first.get_charge(p.second) ;}
00268 template <class Mandatory_fields>
00269 char get_chain_identifier(const std::pair<PDB::Line_format<Mandatory_fields>,std::string>& p) {return p.first.get_chain_identifier(p.second) ;}
00270 template <class Mandatory_fields>
00271 std::string get_residue_name(const std::pair<PDB::Line_format<Mandatory_fields>,std::string>& p) {return p.first.get_residue_name(p.second) ;}
00272 template <class Mandatory_fields>
00273 int get_residue_sequence_number(const std::pair<PDB::Line_format<Mandatory_fields>,std::string>& p) {return p.first.get_residue_sequence_number(p.second) ;}
00274 template <class Mandatory_fields>
00275 char get_insertion_code(const std::pair<PDB::Line_format<Mandatory_fields>,std::string>& p) {return p.first.get_insertion_code(p.second) ;}
00276 template <class Mandatory_fields>
00277 char get_x(const std::pair<PDB::Line_format<Mandatory_fields>,std::string>& p) {return p.first.get_x(p.second) ;}
00278 template <class Mandatory_fields>
00279 char get_y(const std::pair<PDB::Line_format<Mandatory_fields>,std::string>& p) {return p.first.get_y(p.second) ;}
00280 template <class Mandatory_fields>
00281 char get_z(const std::pair<PDB::Line_format<Mandatory_fields>,std::string>& p) {return p.first.get_z(p.second) ;}
00282 }
00283
00284 #endif //ESBTL_PDB_H