atom_classifier.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 #ifndef ESBTL_ATOM_CLASSIFIER_H
00035 #define ESBTL_ATOM_CLASSIFIER_H
00036 
00037 #include <boost/unordered_map.hpp>
00038 #include<boost/lexical_cast.hpp>
00039 #include <boost/algorithm/string.hpp>
00040 #include <iostream>
00041 #include <sstream>
00042 #include <fstream>
00043 
00044 
00045 namespace ESBTL{
00046 
00093 template <class NT,class Atom>
00094 class Radius_of_atom{
00095 private:
00096   typedef Radius_of_atom<NT,Atom>  Self;
00097   NT radius_;
00098   unsigned index_;
00099 
00100 public:
00102   typedef Atom                  Query_type;
00104   typedef std::string           Key_type;
00106   typedef NT                    Value_type;
00107   
00108 
00114   //TODO check why index is useful
00115   Radius_of_atom(const NT& radius,const unsigned& index):radius_(radius),index_(index){}
00116   NT value() const {return radius_;}
00117 
00124   //TODO check why index is useful  
00125   Radius_of_atom(std::stringstream& ss,unsigned index):index_(index){
00126     ss >> radius_; 
00127   }
00128   
00137   template <class Dictionary,class Vector_properties>
00138   static unsigned default_loader(Dictionary& dict,Vector_properties& vect)
00139   {
00141     #include <ESBTL/properties/Tsai_jmb_99_radii.h>
00143   }
00144   
00149   static std::string make_key(const Atom& atom)
00150   {
00151     return atom.residue_name()+atom.atom_name();
00152   }
00153 
00161   template <class Dictionary>
00162   static 
00163   unsigned add_classification(std::stringstream& ss,Dictionary& dict){
00164     std::string resname,atmname;
00165     ss >> resname;
00166     ss >> atmname;
00167     unsigned prop;
00168     ss >> prop;
00169     dict[resname+atmname]=prop;
00170     return prop;
00171   }
00172   
00177   static void handle_extra(std::stringstream&){}
00178     
00183   static
00184   int& index_of_default(){
00185     static int index_of_default=-1;
00186     return index_of_default;
00187   }
00188   
00189 };
00190 
00192 template <class NT,class Atom>
00193 NT get_radius(const Radius_of_atom<NT,Atom>& property){
00194   return property.value();
00195 }
00196 
00197 
00202 template <class NT,class Atom>
00203 class Name_and_radius_of_atom{
00204 private:
00205   typedef Name_and_radius_of_atom<NT,Atom>  Self;
00207   // this value must be updated according to file default_atom_properties.h
00208   static 
00209   unsigned& water_index(){
00210     static unsigned index=9;
00211     return index;
00212   }
00213 
00215   static
00216   std::string water_name(){
00217     static std::string water_name="Owat";
00218     return water_name;
00219   }
00220 
00221 public:
00222   
00223   typedef Atom                  Query_type;
00224   typedef std::string           Key_type;
00225   
00226 
00227   Name_and_radius_of_atom(const std::string& name_,const NT& radius_,const unsigned& index_):name(name_),index(index_),radius(radius_)
00228   {}
00229   
00230   std::string name;
00231   unsigned index;
00232   NT radius;
00233   
00234   bool is_water() const {
00235     assert(index!=water_index() || name==water_name());
00236     return index==water_index();
00237   }
00238     
00239   template <class Dictionary,class Vector_properties>
00240   static unsigned default_loader(Dictionary& dict,Vector_properties& vect)
00241   {
00243     #include <ESBTL/properties/default_atom_properties.h>
00245   }
00246   
00247   static std::string make_key(const Atom& atom)
00248   {
00249     return atom.residue_name()+atom.atom_name();
00250   }
00251   
00252   static
00253   int& index_of_default(){
00254     static int index_of_default=-1;
00255     return index_of_default;
00256   }
00257   
00258 };
00259 
00265 class Name_of_pair{
00266 private:
00267   typedef Name_of_pair Self;
00268 
00269 
00270 public:
00271   
00272 
00273   static
00274   int& index_of_default(){
00275     static int index_of_default=-1;
00276     return index_of_default;
00277   }
00278   
00279   
00280   //~ typedef std::pair<unsigned,unsigned> Key_type;
00281   typedef std::string Key_type;
00282   typedef std::pair<unsigned,unsigned> Query_type;
00283 
00284   Name_of_pair(const std::string& name_,const unsigned& index_):name(name_),index(index_){}
00285   std::string name;
00286   unsigned index;
00287     
00288   template <class Dictionary,class Vector_properties>
00289   static unsigned default_loader(Dictionary& dict,Vector_properties& vect)
00290   {
00292     #include <ESBTL/properties/default_pair_properties.h>
00294   }
00295   
00296   static Key_type make_key(const Query_type& indices)
00297   {
00298     unsigned i0=indices.first;
00299     unsigned i1=indices.second;
00300     if (i0<i1)
00301       return boost::lexical_cast<std::string>(i0)+
00302              boost::lexical_cast<std::string>(i1);
00303       //~ return indices;
00304     //~ return std::make_pair(i1,i0);
00305     return boost::lexical_cast<std::string>(i1)+
00306              boost::lexical_cast<std::string>(i0);
00307   }
00308 };
00309 
00310 
00311 
00317 template<class Properties_>
00318 struct Generic_classifier{
00319   typedef Properties_ Properties;
00320   typedef typename Properties_::Key_type                      Key_type;
00321   typedef typename Properties_::Query_type                    Query_type;
00322   typedef typename std::vector<Properties_>::iterator         Properties_iterator;
00323   typedef typename std::vector<Properties_>::const_iterator   Properties_const_iterator;
00324 private:
00325   typedef boost::unordered_map<Key_type, unsigned>      Internal_map_type;
00326   typedef std::vector<Properties_>                      Internal_vector_type;
00327   
00328   Internal_map_type hmap_;
00329   Internal_vector_type properties_;
00330   unsigned max_index_;
00331   
00332 public:
00333   
00337   Generic_classifier(){
00338     max_index_=Properties_::default_loader(hmap_,properties_);
00339     assert(max_index_==properties_.size());
00340   }
00341   
00343   Generic_classifier(std::string filename,int){
00344     /* may need a map from name to property position in the vector */
00345     /* This map can be filled by a static function of Properties_  */
00346   }
00347   
00379   Generic_classifier(const std::string& filename){
00380     enum Read_state {PROPERTIES, CLASSIFICATION, END, EXTRA,DEFAULT};
00381     
00382     std::ifstream input(filename.c_str());
00383     
00384     if (!input){
00385       std::cerr << "Cannot open file " << filename << std::endl;
00386       exit( EXIT_FAILURE);
00387     }
00388     
00389     std::string buffer;
00390     Read_state state=END;
00391 
00392     std::map<unsigned,Properties> properties_map;
00393     unsigned max_property=0;
00394     
00395     
00396     while(input){
00397       std::getline(input,buffer); //read a complete line
00398       
00399       if (!input) {
00400         if (input.eof()) break;
00401         std::cerr << "Fatal error: Error while reading file "<< filename <<"\n";
00402         exit( EXIT_FAILURE );
00403       }
00404       
00405       boost::trim(buffer); //remove white space at the beginning and at the end of the line
00406       if (buffer.empty() || buffer[0] == '#') continue; //handle comments and empty lines
00407       
00408       switch (state){
00409         case END:
00410           if (buffer == "PROPERTIES")     {state=PROPERTIES;     break;}
00411           if (buffer == "CLASSIFICATION") {state=CLASSIFICATION; break;}
00412           if (buffer == "EXTRA")          {state=EXTRA;          break;}
00413           if (buffer == "DEFAULT")          {state=DEFAULT;          break;}
00414           std::cerr << "Fatal error: Error while reading file "<< filename;
00415           std::cerr << ", unexpected <|" << buffer << "|> found.\n";
00416           exit( EXIT_FAILURE );
00417         case CLASSIFICATION:
00418         {
00419           if (buffer=="END")              {state=END;            break;}
00420           std::stringstream ss (std::stringstream::in | std::stringstream::out);
00421           ss << buffer;
00422           //inside a function
00423           unsigned index=Properties::add_classification(ss,hmap_);
00424           if (max_property <  index) max_property=index;
00425           break;
00426         }
00427         case PROPERTIES:
00428         {
00429           if (buffer=="END")              {state=END;            break;}
00430           std::stringstream ss (std::stringstream::in | std::stringstream::out);
00431           ss << buffer;
00432           unsigned index;
00433           ss >> index;
00434           //inside a function
00435           assert(properties_map.find(index)==properties_map.end());
00436           properties_map.insert(std::make_pair(index,Properties(ss,index)));
00437           break;
00438         }        
00439         case DEFAULT:
00440         {
00441           if (buffer=="END")              {state=END;            break;}
00442           unsigned i;
00443           std::stringstream ss (std::stringstream::in | std::stringstream::out);
00444           ss << buffer;
00445           ss >> i;
00446           if ( max_property<i ) max_property=i;
00447           Properties::index_of_default()=i;
00448           break;
00449         }
00450         case EXTRA:
00451         {
00452           if (buffer=="END")              {state=END;            break;}
00453           //call some function
00454           std::stringstream ss (std::stringstream::in | std::stringstream::out);
00455           ss << buffer;          
00456           Properties::handle_extra(ss);
00457           break;
00458         }
00459       };
00460     }
00461     
00462     
00463     unsigned i=0;
00464     for (typename std::map<unsigned,Properties>::const_iterator it=properties_map.begin();it!=properties_map.end();++it){
00465       if (i++ != it->first){
00466         std::cerr << "Fatal error: properties number " << i-1 << " could not be found in file " << filename <<"\n";
00467         exit( EXIT_FAILURE );
00468       }
00469       properties_.push_back(it->second);
00470     }  
00471     
00472     if (i <= max_property){
00473       std::cerr << "Fatal error: Up to " << max_property+1 << " properties are used, but only " << i << " are declared.\n";
00474       exit( EXIT_FAILURE );    
00475     }
00476     
00477     max_index_=i;
00478     
00479   }
00480   
00484   const Properties& get_properties(unsigned i) const{
00485     assert(i <= max_index_);
00486     return properties_[i];
00487   }
00488     
00492   const Properties& get_properties(const Query_type& query) const{
00493     typename Internal_map_type::const_iterator it=hmap_.find( Properties_::make_key(query) );
00494     if ( it==hmap_.end() ){
00495       if (Properties::index_of_default()!=-1)
00496         return properties_[Properties::index_of_default()];
00497       std::cerr << "Fatal error: Could not find an entry for " << Properties_::make_key(query);
00498       std::cerr << " and no default have been defined.\n";
00499       exit( EXIT_FAILURE );
00500     }
00501     return properties_[it->second];
00502   }
00503   
00505   unsigned number_of_properties() const {return max_index_;}
00506   
00508   Properties_iterator properties_begin(){ return properties_.begin();}
00510   Properties_const_iterator properties_begin() const { return properties_.begin();}
00512   Properties_iterator properties_end(){ return properties_.end(); }
00514   Properties_const_iterator properties_end() const { return properties_.end(); }
00515   
00516 };
00517 
00518 //TODO better specify this class: value and Value_type are not in the concept.
00523 template <class Atom_classifier>
00524 struct Weight_of_atoms{
00525   
00527   Weight_of_atoms(const Atom_classifier* atom_classifier):atom_classifier_(atom_classifier){}
00528     
00533   typename Atom_classifier::Properties::Value_type
00534   operator()(const typename Atom_classifier::Query_type& atom) const {
00535     typename Atom_classifier::Properties::Value_type value=get_radius(atom_classifier_->get_properties(atom));
00536     return value*value;
00537   }
00538 private:
00539   const Atom_classifier* atom_classifier_;
00540 };
00541 
00542 }//namespace ESBTL
00543 
00544 #endif //ESBTL_ATOM_CLASSIFIER_H