occupancy_handlers.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_OCCUPANCY_HANDLERS_H
00036 #define ESBTL_OCCUPANCY_HANDLERS_H
00037 
00038 #include <set>
00039 #include <iostream>
00040 
00041 namespace ESBTL{
00042 
00070   template <class Line_format>
00071   struct No_occupancy_policy{
00072     int add_or_postpone(const Line_format& line_format,const std::string& line,int system_index) const{
00073       double occupancy_value=line_format.get_occupancy(line);
00074       if (occupancy_value==1. || line_format.get_alternate_location(line)!=' ')
00075         return system_index;
00076       std::cerr << "Fatal error: Occupancy factor < 1. No occupancy selection policy is provided to handle line\n";
00077       std::cerr << "<|" << line << "|>\n";
00078       exit(EXIT_FAILURE);
00079     }
00080     
00081     template <class Builder>
00082     int finalize(Builder&) const {return 0;}
00083   };
00084 
00085 
00090   template <class Line_format>
00091   struct Accept_all_occupancy_policy{
00092     int add_or_postpone(const Line_format& ,const std::string& ,int system_index) const {
00093       return system_index;
00094     }
00095     
00096     template <class Builder>
00097     int finalize(Builder&) const {return 0;}
00098   };
00099 
00104   template <class Line_format>
00105   struct Accept_none_occupancy_policy{
00106     int add_or_postpone(const Line_format& line_format,const std::string& line,int system_index) const {
00107       double occupancy_value=line_format.get_occupancy(line);
00108       if (occupancy_value==1. || line_format.get_alternate_location(line)!=' ')
00109         return system_index;      
00110       return DISCARD;
00111     }
00112     
00113     template <class Builder>
00114     int finalize(Builder&) const {return 0;}
00115   };
00116 
00118   namespace internal{
00119     
00120     template <class Line_format,bool take_max>
00121     class Min_or_max_occupancy_policy{
00122     protected:
00123       typedef std::map<double,std::pair<int,std::list<std::string> > > Info;
00124       Info lines;
00125       double min_or_max_occupancy;
00126       
00127       Min_or_max_occupancy_policy():min_or_max_occupancy(take_max?0.:1.){}
00128       
00129       void add_line(double occupancy_value,const std::string& line,int system_index){
00130         typename Info::iterator it=lines.find(occupancy_value);
00131         if (it==lines.end())
00132           it=lines.insert(
00133               std::make_pair(occupancy_value,
00134                              std::make_pair(system_index,std::list<std::string>())) 
00135           ).first;
00136         it->second.second.push_back(line);
00137       }
00138       
00139     public:
00140       int add_or_postpone(const Line_format& line_format,const std::string& line,int system_index){
00141         double occupancy_value=line_format.get_occupancy(line);
00142         if (occupancy_value==1. || line_format.get_alternate_location(line)!=' ')
00143           return system_index;
00144         
00145         bool do_take_it=take_max?
00146                           occupancy_value >= min_or_max_occupancy:
00147                           occupancy_value <= min_or_max_occupancy;
00148           
00149         if (do_take_it){
00150           add_line(occupancy_value,line,system_index);
00151           min_or_max_occupancy=occupancy_value;
00152         }
00153         
00154         return DISCARD;
00155       }
00156       
00157       template <class Builder>
00158       int finalize(Builder& builder) const {
00159         if (lines.empty())
00160           return 0;
00161         if (min_or_max_occupancy==0.5){
00162           std::cerr << "Fatal error: The atom occupancy selection policy is ambiguous is that case (0.5)\n";
00163           exit(EXIT_FAILURE);
00164         }
00165         int lines_added=0;
00166         Info::const_iterator it=lines.find(min_or_max_occupancy);
00167         for (std::list<std::string>::const_iterator cur=it->second.second.begin();
00168              cur!=it->second.second.end(); ++cur)
00169         {
00170           ++lines_added;
00171           builder.interpret_line(Line_format(*cur),*cur,it->second.first);
00172         }
00173         
00174         return lines_added;
00175       }
00176     };
00177     
00178   }//namespace internal
00189   template<class Line_format>
00190   class Max_occupancy_policy: public internal::Min_or_max_occupancy_policy<Line_format,true>{};
00191 
00192 
00201   template<class Line_format>
00202   class Min_occupancy_policy: public internal::Min_or_max_occupancy_policy<Line_format,false>{};
00203   
00213   template <class Line_format>
00214   class Atom_list_occupancy_policy{
00215     std::set<int> selected_atoms;
00216   public:  
00223     template <class Iterator>
00224     Atom_list_occupancy_policy(Iterator begin,Iterator end){
00225       selected_atoms.insert(begin,end);
00226     }
00227   
00228     int add_or_postpone(const Line_format& line_format,const std::string& line,int system_index) const {
00229       double occupancy_value=line_format.get_occupancy(line);
00230       if (occupancy_value==1. || line_format.get_alternate_location(line)!=' ')
00231         return system_index;
00232       
00233       if (selected_atoms.find(line_format.get_atom_serial_number(line))!=selected_atoms.end())
00234         return system_index;
00235       
00236       return DISCARD;
00237     }
00238     
00239     template <class Builder>
00240     int finalize(Builder&) const {
00241       return 0;
00242     }
00243   };
00244 } //namespace ESBTL
00245 
00246 
00247 #endif //ESBTL_OCCUPANCY_HANDLERS_H