molecular_system.h
Go to the documentation of this file.
00001 // Copyright (c) 2009-2010  INRIA Sophia-Antipolis (France).
00002 // All rights reserved.
00003 //
00004 //This file is part of ESBTL.
00005 //
00006 //ESBTL is free software: you can redistribute it and/or modify
00007 //it under the terms of the GNU General Public License as published by
00008 //the Free Software Foundation, either version 3 of the License, or
00009 //(at your option) any later version.
00010 //
00011 //ESBTL is distributed in the hope that it will be useful,
00012 //but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 //MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 //GNU General Public License for more details.
00015 //
00016 //You should have received a copy of the GNU General Public License
00017 //along with ESBTL.  If not, see <http://www.gnu.org/licenses/>.
00018 //
00019 //
00020 //Additional permission under GNU GPL version 3 section 7
00021 //
00022 //If you modify this Library, or any covered work, by linking or
00023 //combining it with CGAL (or a modified version of that library), the
00024 //licensors of this Library grant you additional permission to convey
00025 //the resulting work. Corresponding Source for a non-source form of
00026 //such a combination shall include the source code for the parts of CGAL
00027 //used as well as that of the covered work. 
00028 //
00029 //
00030 //
00031 // Author(s)     :  Sébastien Loriot
00032 
00033 
00034 
00035 #ifndef ESBTL_MOLECULAR_SYSTEM_H
00036 #define ESBTL_MOLECULAR_SYSTEM_H
00037 
00038 #include <map>
00039 #include <list>
00040 #include <vector>
00041 #include <cassert>
00042 #include <string>
00043 #include <iostream>
00044 #include <boost/tuple/tuple.hpp>
00045 #include <ESBTL/iterators.h>
00046 #include <ESBTL/constants.h>
00047 
00052 namespace ESBTL{
00053 
00059 template <class Items,class Point>
00060 class Molecular_system{
00061   typedef Molecular_system<Items,Point>                                                 Self;
00062 public:
00063   typedef typename Items::template   Model_wrapper<Molecular_system,Point>::Type        Model;
00064   typedef typename Items::template   Chain_wrapper<Molecular_system,Point>::Type        Chain;
00065   typedef typename Items::template    Atom_wrapper<Molecular_system,Point>::Type         Atom;
00066   typedef typename Items::template Residue_wrapper<Molecular_system,Point>::Type      Residue;
00067   typedef std::map<int,Model>                                                   Model_container;   
00068 
00069   //iterators
00070   //---------
00071   static const Model& dereference (typename Model_container::const_iterator it) {return it->second;}
00072   static Model& dereference (typename Model_container::iterator it) {return it->second;}
00073 
00075   typedef internal::Model_iterator_from_system<Self,false>                        Models_iterator;
00077   typedef internal::Model_iterator_from_system<Self,true>                   Models_const_iterator;
00078 
00080   Models_iterator models_begin() {return Models_iterator(model_container_.begin()); }
00082   Models_iterator models_end()   {return Models_iterator(model_container_.end()); }
00084   Models_const_iterator models_begin() const {return Models_const_iterator(model_container_.begin());}
00086   Models_const_iterator models_end()   const {return Models_const_iterator(model_container_.end());  }
00087   //---------
00088   
00089   Molecular_system(int index,std::string name="no_name"):name_(name),index_(index),alternate_location_(' '){}
00090 
00091   template<class Line_format>
00092   void interpret_line(const Line_format& line_format,const std::string& line,int current_model){
00093     Model& model=get_or_create_model(current_model);
00094     Chain& chain=model.get_or_create_chain(line_format,line);
00095     Residue& residue=chain.get_or_create_residue(line_format,line);
00096     residue.add_atom(line_format,line);
00097   }
00098 
00099   bool has_no_model() const{
00100     return model_container_.empty();
00101   }
00102 
00103   bool has_model(int i) const{
00104     return model_container_.find(i)!=model_container_.end();
00105   }  
00106   
00107   size_t number_of_models() const {
00108     return model_container_.size();
00109   }
00110   
00111   void set_altloc(char c) {alternate_location_=c;}
00112   
00113   //member variables
00114   //DECLARE_AND_ACCESS(model_container,Model_container)
00115   DECLARE_AND_ACCESS(name,std::string)
00116   DECLARE_AND_ACCESS(index,int)
00117   DECLARE_AND_ACCESS(alternate_location,char)
00118   
00119   //create the model if it does not exist
00120   Model& get_or_create_model(int i){
00121     typename Model_container::iterator itm=model_container_.find(i);
00122     if (itm==model_container_.end()){
00123       itm=model_container_.insert( std::make_pair(i,Model(i,*this)) ).first;
00124     }
00125     return itm->second;
00126   }
00127   
00128   Model& get_model(int i){
00129     typename Model_container::iterator itm=model_container_.find(i);
00130     if (itm==model_container_.end()){std::cerr <<"Cannot find model " << i << std::endl; exit(EXIT_FAILURE);}
00131     return itm->second;    
00132   }
00133 
00134   //Model_container& model_container(){return model_container_;}
00135 private:
00136   Model_container model_container_;
00137 };
00138 
00142 template<class System_>
00143 class Molecular_model{
00144  
00145 public:
00146   typedef System_                          System;
00147   typedef typename System::Chain           Chain;
00148   typedef std::map<char,Chain>             Chain_container;
00149 private:
00150   typedef Molecular_model<System_>         Self;
00151   const System& system_;
00152   Chain_container chain_container_;
00153 public:
00154   const System& system() const {return system_;}
00155   
00156   Molecular_model(int nbm,const System& sys):system_(sys),model_number_(nbm){}
00157 
00158   template <class Line_format>
00159   Chain& get_or_create_chain(const Line_format& line_format,const std::string& line){
00160     char ch=line_format.get_chain_identifier(line);
00161     typename Chain_container::iterator itch=chain_container_.find(ch);
00162     if (itch==chain_container_.end())
00163       itch=chain_container_.insert(std::make_pair(ch,Chain(line_format,line,*this))).first;
00164     return itch->second;
00165   }
00166   
00167   Chain& get_or_create_chain(char id){
00168     typename Chain_container::iterator itch=chain_container_.find(id);
00169     if (itch==chain_container_.end())
00170       itch=chain_container_.insert(std::make_pair(id,Chain(id,*this))).first;
00171     return itch->second;    
00172   }
00173 
00174   const Chain& get_chain(char id) const {
00175     typename Chain_container::const_iterator itch=chain_container_.find(id);
00176     assert (itch!=chain_container_.end());
00177     return itch->second;    
00178   }
00179 
00180   const typename System::Residue& get_residue(char ch_id,int ressn,char insc=' ') const {
00181     return get_chain(ch_id).get_residue(ressn,insc);
00182   }
00183   
00184   const typename System::Atom& get_atom(char ch_id,int ressn,char insc,unsigned atom_sn) const {
00185     return get_chain(ch_id).get_residue(ressn,insc).get_atom(atom_sn);
00186   }
00187   
00188   size_t number_of_chains() const {
00189     return chain_container_.size();
00190   }
00191   
00192   size_t number_of_residues() const {
00193     size_t total=0;
00194     for (typename Chain_container::const_iterator it=chain_container_.begin();it!=chain_container_.end();++it)
00195       total+=it->second.number_of_residues();
00196     return total;
00197   }
00198 
00199   size_t number_of_atoms() const {
00200     size_t total=0;
00201     for (typename Chain_container::const_iterator it=chain_container_.begin();it!=chain_container_.end();++it)
00202       total+=it->second.number_of_atoms();
00203     return total;
00204   }  
00205   //iterators
00206   //---------
00207   //functions needed by generic iterator in iterators.h 
00208   static const Chain& dereference (typename Chain_container::const_iterator it) {return it->second;}
00209   static Chain& dereference (typename Chain_container::iterator it) {return it->second;}
00210   
00212   typedef internal::Chains_iterator_from_model<Self,true>  Chains_const_iterator;
00214   typedef internal::Chains_iterator_from_model<Self,false> Chains_iterator;
00215   
00217   Chains_iterator chains_begin() {return Chains_iterator(chain_container_.begin());}
00219   Chains_iterator chains_end()   {return Chains_iterator(chain_container_.end());}
00220 
00222   Chains_const_iterator chains_begin() const {return Chains_const_iterator(chain_container_.begin());}
00224   Chains_const_iterator chains_end()   const {return Chains_const_iterator(chain_container_.end());}  
00225   
00227   typedef internal::Residues_iterator_from_model<Self,true>  Residues_const_iterator;
00229   typedef internal::Residues_iterator_from_model<Self,false> Residues_iterator;
00230 
00232   Residues_iterator residues_begin() {return Residues_iterator(*this);}
00234   Residues_iterator residues_end()   {return Residues_iterator(*this,true);}
00235 
00237   Residues_const_iterator residues_begin() const {return Residues_const_iterator(*this);}
00239   Residues_const_iterator residues_end()   const {return Residues_const_iterator(*this,true);}  
00240   
00241   
00243   typedef internal::Atoms_iterator_from_model<Self,true>  Atoms_const_iterator;
00245   typedef internal::Atoms_iterator_from_model<Self,false> Atoms_iterator;
00246   
00248   Atoms_iterator atoms_begin() {return Atoms_iterator(*this);}
00250   Atoms_iterator atoms_end()   {return Atoms_iterator(*this,true);}
00251 
00253   Atoms_const_iterator atoms_begin() const {return Atoms_const_iterator(*this);}
00255   Atoms_const_iterator atoms_end()   const {return Atoms_const_iterator(*this,true);}
00256   //---------
00257   
00258   
00259   //DECLARE_AND_ACCESS(chain_container,Chain_container)
00260   DECLARE_AND_ACCESS(model_number,int)
00261 
00262 };
00263 
00264 
00268 template<class System>
00269 class Molecular_chain{
00270 public:
00271   typedef typename System::Residue                  Residue;
00272   typedef typename Residue::Atom                    Atom;
00273   typedef std::map<std::pair<int,char>,Residue>     Residue_container;     
00274   typedef typename System::Model                    Model;
00275 private:
00276   typedef Molecular_chain<System>                   Self;
00277   const Model& model_;
00278   Residue_container residue_container_;
00279 public:
00280   
00281   template<class Line_format>  
00282   Molecular_chain(const Line_format& line_format,const std::string& line, const Model& mod):
00283     model_(mod),
00284     chain_identifier_(line_format.get_chain_identifier(line)) {}
00285 
00286   Molecular_chain(char id, const Model& mod):model_(mod),chain_identifier_(id) {}  
00287       
00288   const Model& model() const {return model_;}
00289 
00290   template<class Line_format>
00291   Residue& get_or_create_residue(const Line_format& line_format,const std::string& line){
00292     int ressn=line_format.get_residue_sequence_number(line);
00293     char insc=line_format.get_insertion_code(line);
00294     typename Residue_container::iterator it=residue_container_.find(std::make_pair(ressn,insc));
00295     if (it==residue_container_.end())
00296       it=residue_container_.insert( std::make_pair(std::make_pair(ressn,insc),Residue(line_format,line,*this) ) ).first;
00297     return it->second;
00298   }
00299   
00300   Residue& get_or_create_residue(const std::string& resname,int ressn,char insc){
00301     typename Residue_container::iterator it=residue_container_.find(std::make_pair(ressn,insc));
00302     if (it==residue_container_.end())
00303       it=residue_container_.insert( std::make_pair(std::make_pair(ressn,insc),Residue(resname,ressn,insc,*this) ) ).first;
00304     return it->second;
00305   }
00306   
00307   const Residue& get_residue(int ressn,char insc=' ') const {
00308     typename Residue_container::const_iterator it=residue_container_.find(std::make_pair(ressn,insc));
00309     assert (it!=residue_container_.end());
00310     return it->second;    
00311   }
00312   
00313   const typename System::Atom get_atom(int ressn,char insc,unsigned atom_sn) const {
00314     return get_residue(ressn,insc).get_atom(atom_sn);
00315   }
00316   
00317   size_t number_of_residues() const {
00318     return residue_container_.size();
00319   }
00320 
00321   size_t number_of_atoms() const {
00322     size_t total=0;
00323     for (typename Residue_container::const_iterator it=residue_container_.begin();it!=residue_container_.end();++it)
00324       total+=it->second.number_of_atoms();
00325     return total;
00326   }  
00327   
00328   //iterators
00329   //---------
00330   //functions needed by generic iterator in iterators.h 
00331   static const Residue& dereference (typename Residue_container::const_iterator it) {return it->second;}
00332   static Residue& dereference (typename Residue_container::iterator it) {return it->second;}
00333   
00335   typedef internal::Residues_iterator_from_chain<Self,true>  Residues_const_iterator;
00337   typedef internal::Residues_iterator_from_chain<Self,false> Residues_iterator;
00338   
00340   Residues_iterator residues_begin() {return Residues_iterator(residue_container_.begin());}
00342   Residues_iterator residues_end()   {return Residues_iterator(residue_container_.end());}  
00343 
00345   Residues_const_iterator residues_begin() const {return Residues_const_iterator(residue_container_.begin());}
00347   Residues_const_iterator residues_end()   const {return Residues_const_iterator(residue_container_.end());}
00348   
00350   typedef internal::Atoms_iterator_from_chain<Self,true>  Atoms_const_iterator;
00352   typedef internal::Atoms_iterator_from_chain<Self,false> Atoms_iterator;
00353   
00355   Atoms_iterator atoms_begin() {return Atoms_iterator(*this);}
00357   Atoms_iterator atoms_end()   {return Atoms_iterator(*this,true);}  
00358 
00360   Atoms_const_iterator atoms_begin() const {return Atoms_const_iterator(*this);}
00362   Atoms_const_iterator atoms_end()   const {return Atoms_const_iterator(*this,true);}  
00363   //-------
00364   
00365   DECLARE_AND_ACCESS(chain_identifier,char)
00366 };
00367 
00371 template<class System>
00372 class Molecular_residue{
00373 public:
00374   typedef typename System::Atom          Atom;
00375   typedef std::map<unsigned,Atom>        Atom_container;   
00376   typedef typename System::Chain         Chain;
00377 private:
00378   typedef Molecular_residue<System>      Self;
00379   const Chain& chain_;
00380 protected:
00381   Atom_container atom_container_;
00382 public:
00383   const Chain& chain() const {return chain_;}
00384   char chain_identifier() const {return chain_.chain_identifier();}
00385   
00386   template<class Line_format>
00387   Molecular_residue(const Line_format& line_format, const std::string& line,const Chain& ch):
00388     chain_(ch),
00389     residue_name_(line_format.get_residue_name(line)),
00390     residue_sequence_number_(line_format.get_residue_sequence_number(line)),
00391     insertion_code_(line_format.get_insertion_code(line)){}
00392 
00393   Molecular_residue(const std::string& resname,int index,char insc,const Chain& ch):
00394     chain_(ch),residue_name_(resname),residue_sequence_number_(index),insertion_code_(insc){}
00395       
00396   template<class Line_format>    
00397   void add_atom(const Line_format& line_format, const std::string& line)
00398   {
00399     unsigned sn=line_format.get_atom_serial_number(line);
00400     assert (atom_container_.find(sn)==atom_container_.end() || !"Two atoms with same serial numbers.");
00401     atom_container_.insert(std::make_pair(sn,Atom(line_format,line,*this)));
00402   }
00403 
00404   size_t number_of_atoms() const {
00405     return atom_container_.size();
00406   }
00407   
00408   const Atom& get_atom(unsigned sn) const {
00409     typename Atom_container::const_iterator  it=atom_container_.find(sn);
00410     assert(atom_container_.find(sn)!=atom_container_.end());
00411     return it->second;
00412   }
00413   
00414   //iterators
00415   //---------
00416   //functions needed by generic iterator in iterators.h 
00417   static const Atom& dereference (typename Atom_container::const_iterator it) {return it->second;}
00418   static Atom& dereference (typename Atom_container::iterator it) {return it->second;}
00419   
00421   typedef internal::Atoms_iterator_from_residue<Self,true>  Atoms_const_iterator;
00423   typedef internal::Atoms_iterator_from_residue<Self,false> Atoms_iterator;
00424   
00426   Atoms_iterator atoms_begin() {return Atoms_iterator(atom_container_.begin(),atom_container_.end());}
00428   Atoms_iterator atoms_end()   {return Atoms_iterator(atom_container_.end());}  
00429 
00431   Atoms_const_iterator atoms_begin() const {return Atoms_const_iterator(atom_container_.begin(),atom_container_.end());}
00433   Atoms_const_iterator atoms_end()   const {return Atoms_const_iterator(atom_container_.end());}
00434   //-------  
00435   
00436   DECLARE_AND_ACCESS(residue_name,std::string)
00437   DECLARE_AND_ACCESS(residue_sequence_number,int)
00438   DECLARE_AND_ACCESS(insertion_code,char)
00439 };
00440 
00441 
00446 template<class System_,class Point>
00447 class Molecular_atom: public Point{
00448 public:
00449   typedef System_                                      System;
00450   typedef Point                                        Point_3;
00451   typedef typename System::Residue                     Residue;
00452 
00453 private:
00454   const Residue* residue_;
00455 public:
00456   
00457   template <class Line_format,class Residue_type>
00458   Molecular_atom(const Line_format& line_format, const std::string& line,const Residue_type& res):
00459     Point(line_format.get_x(line),line_format.get_y(line),line_format.get_z(line)),
00460     residue_(static_cast<const Residue*>(&res)),
00461     is_hetatm_(line_format.is_hetatm()),
00462     atom_serial_number_(line_format.get_atom_serial_number(line)),
00463     atom_name_(line_format.get_atom_name(line)),
00464     alternate_location_(line_format.get_alternate_location(line)),
00465     occupancy_(line_format.get_occupancy(line)),
00466     temperature_factor_(line_format.get_temperature_factor(line)),
00467     element_(line_format.get_element(line)),
00468     charge_(line_format.get_charge(line))
00469   {
00470     //IN SOME FILES ... ELEMENT_SYMBOL IS CORRUPTED BY PREVIOUS FIELDS
00471     //~ if (element_==" ")
00472       //~ element_=line_format.get_element_using_atom_name(line);
00473     //~ assert(element_==line_format.get_element_using_atom_name(line));
00474   }
00475   
00476   Molecular_atom():Point(),residue_(NULL){}
00477   //TODO should use the number type of the Point 
00478   Molecular_atom(double x,double y,double z):Point(x,y,z),residue_(NULL){}
00479 
00480   //System functions
00481   int system_index() const {return residue_->chain().model().system().index();};
00482   
00483   //Chain functions
00484   char chain_identifier() const {return residue_->chain().chain_identifier();}
00485   //Residue functions
00486   const Residue& residue() const {return *residue_;}
00487   const std::string& residue_name() const {return residue_->residue_name();}
00488   int residue_sequence_number() const {return residue_->residue_sequence_number();}
00489   char insertion_code() const {return residue_->insertion_code();}
00490   
00491   //member variables
00492   DECLARE_AND_ACCESS(is_hetatm,bool)
00493   DECLARE_AND_ACCESS(atom_serial_number,int)
00494   DECLARE_AND_ACCESS(atom_name,std::string)
00495   DECLARE_AND_ACCESS(alternate_location,char)
00496   DECLARE_AND_ACCESS(occupancy,double)
00497   DECLARE_AND_ACCESS(temperature_factor,double)
00498   DECLARE_AND_ACCESS(element,std::string)
00499   DECLARE_AND_ACCESS(charge,int)
00500 };
00501 
00502 
00508 struct Default_system_items{
00509   template <class System,class Point>
00510   struct Model_wrapper{
00511     typedef Molecular_model<System>         Type;
00512   };
00513   
00514   template <class System,class Point>
00515   struct Chain_wrapper{
00516     typedef Molecular_chain<System>         Type;
00517   };
00518   
00519   template <class System,class Point>
00520   struct Residue_wrapper{
00521     typedef Molecular_residue<System>       Type;
00522   };
00523   
00524   template <class System,class Point>
00525   struct Atom_wrapper{
00526     typedef Molecular_atom<System,Point>  Type;
00527   };  
00528 };
00529 
00530 
00531 //global access functions
00532 //for chains
00533   template <class System>
00534   char get_chain_identifier(const Molecular_chain<System>& c) {return c.chain_identifier();}
00535 //for residues
00536   template <class System>
00537   const std::string& get_residue_name(const Molecular_residue<System>& r) {return r.residue_name();}
00538   template <class System>
00539   int get_residue_sequence_number(const Molecular_residue<System>& r) {return r.residue_sequence_number();}
00540   template <class System>
00541   char get_insertion_code(const Molecular_residue<System>& r) {return r.insertion_code();}
00542 //for atoms
00543   template <class System,class Point>
00544   bool get_is_hetatm(const Molecular_atom<System,Point>& a) {return a.is_hetatm() ;}
00545   template <class System,class Point>
00546   int get_atom_serial_number(const Molecular_atom<System,Point>& a) {return a.atom_serial_number() ;}
00547   template <class System,class Point>
00548   const std::string& get_atom_name(const Molecular_atom<System,Point>& a) {return a.atom_name() ;}
00549   template <class System,class Point>
00550   char get_alternate_location(const Molecular_atom<System,Point>& a) {return a.alternate_location() ;}
00551   template <class System,class Point>
00552   double get_occupancy(const Molecular_atom<System,Point>& a) {return a.occupancy() ;}
00553   template <class System,class Point>
00554   double get_temperature_factor(const Molecular_atom<System,Point>& a) {return a.temperature_factor() ;}
00555   template <class System,class Point>
00556   const std::string& get_element(const Molecular_atom<System,Point>& a) {return a.element() ;}
00557   template <class System,class Point>
00558   int get_charge(const Molecular_atom<System,Point>& a) {return a.charge() ;}
00559   template <class System,class Point>
00560   char get_chain_identifier(const Molecular_atom<System,Point>& a) {return a.chain_identifier() ;}
00561   template <class System,class Point>
00562   const std::string& get_residue_name(const Molecular_atom<System,Point>& a) {return a.residue_name() ;}
00563   template <class System,class Point>
00564   int get_residue_sequence_number(const Molecular_atom<System,Point>& a) {return a.residue_sequence_number() ;}
00565   template <class System,class Point>
00566   char get_insertion_code(const Molecular_atom<System,Point>& a) {return a.insertion_code() ;}
00567   template <class System,class Point>
00568   char get_x(const Molecular_atom<System,Point>& a) {return a.x() ;}
00569   template <class System,class Point>
00570   char get_y(const Molecular_atom<System,Point>& a) {return a.y() ;}
00571   template <class System,class Point>
00572   char get_z(const Molecular_atom<System,Point>& a) {return a.z() ;}
00573   
00574 //~ //function to insert a set water molecule in as a system
00575 //~ template<class Input_iterator,class System>
00576 //~ void insert_atoms(Input_iterator first,Input_iterator last,System& system,int modelid=1,char chainid='Z',std::string resname="HOH",int starting_res_index=1){
00577   //~ typename System::Model& model=system.get_or_create_model(modelid);
00578   //~ typename System::Chain& chain=model.get_or_create_chain(chainid);
00579   //~ int res_index=starting_res_index-1;
00580   //~ char insc=' ';
00581   //~ for (Input_iterator it=first; it!=last;++it){
00582     //~ typename System::Residue& residue=chain.get_or_create_residue(resname,++res_index,insc);
00583     //~ residue.add_coarse_atom(*it,0);
00584   //~ }
00585 //~ }
00586   
00587 
00588 }// namespace ESBTL
00589 
00590 #endif //ESBTL_MOLECULAR_SYSTEM_H