system_updater_from_xdrfile.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 SYSTEM_UPDATER_FROM_XDRFILE_H
00036 #define SYSTEM_UPDATER_FROM_XDRFILE_H
00037 
00038 // Require library xdrfile available at ftp://ftp.gromacs.org/pub/contrib/xdrfile-1.1.tar.gz
00039 // and refer to http://wiki.gromacs.org/index.php/XTC_Library
00040 //For more info on how to read the xtc file format refer to
00041 // http://www.gromacs.org/documentation/reference_4.0/online/xtc.html
00042 
00043 
00044 #include <cstdlib>
00045 #include <boost/tuple/tuple.hpp>
00046 #include <iostream>
00047 
00048 #define CPLUSPLUS
00049 #include <xdrfile/xdrfile.h>
00050 #undef CPLUSPLUS
00051 
00052 
00053 
00054 namespace ESBTL{
00055   
00068   template <class System>
00069   class System_updater_from_xdrfile{
00070     typedef std::map<unsigned,typename System::Atom*> Map_id_to_atom;
00071     Map_id_to_atom selected_atoms_;
00072     
00073     XDRFILE* input_file_;
00074     unsigned first_frame_id_;
00075     unsigned last_frame_id_;
00076     unsigned nb_atoms_to_read_;
00077     unsigned current_frame_;
00078   public:
00079     
00091     template <class System_iterator>
00092     System_updater_from_xdrfile(System_iterator begin, System_iterator end,unsigned model_selected_,const std::string& xtc_fname,
00093                                 unsigned max_atoms,unsigned read_from=1,
00094                                 unsigned read_to=std::numeric_limits<unsigned>::max() ):first_frame_id_(read_from),last_frame_id_(read_to),nb_atoms_to_read_(max_atoms),current_frame_(0)
00095     {
00096       input_file_=xdrfile_open(xtc_fname.c_str(), "r");
00097       if (input_file_ == NULL){
00098         std::cerr << "Error while opening xtc file " << xtc_fname << std::endl;
00099         exit (EXIT_FAILURE);
00100       }
00101       
00102       for (System_iterator it_sys=begin;it_sys!=end;++it_sys){
00103         typename System::Model& model=it_sys->get_model(model_selected_);
00104         for (typename System::Model::Atoms_iterator it_atm=model.atoms_begin();it_atm!=model.atoms_end();++it_atm){
00105           assert( selected_atoms_.find(it_atm->atom_serial_number())==selected_atoms_.end() );
00106           selected_atoms_.insert(std::make_pair(it_atm->atom_serial_number(),&(*it_atm)));
00107         }
00108       }
00109       
00110       //check the file contains at least one frame
00111       int magic=0;
00112       int result=xdrfile_read_int(&magic,1,input_file_);
00113       if (result==0){
00114         std::cerr << "xtc file provided contains no frame: error while reading magic number" << std::endl;
00115         exit (EXIT_FAILURE);
00116       }
00117       assert (magic==1995); //checks XDR magic number    
00118       
00119       if (first_frame_id_!=1)
00120         next_frame(true);
00121       
00122       assert(current_frame_+1==first_frame_id_);
00123     }
00124     
00125     ~System_updater_from_xdrfile(){
00126       //only when reading stops at a given frame id
00127       if (input_file_!=NULL)
00128         xdrfile_close(input_file_);
00129     }
00130       
00131     
00132     //return true if next_frame can be loaded
00133     //return in addition the corresponding simulation step and the simulation time.
00139     boost::tuple<bool,double,int> next_frame(bool is_init=false){
00140       if (!has_more_frames())
00141         return boost::make_tuple(false,-1,-1);
00142       
00143       int magic,result, natoms,step;
00144       float time, prec, box[9];//, min[3], max[3];
00145       float xyz[3*nb_atoms_to_read_];
00146 
00147       do
00148       {
00149         ++current_frame_;
00150        // Read the compressed xtc file
00151         xdrfile_read_int(&natoms,1,input_file_); // reads number of atoms in the frame
00152         assert(natoms == static_cast<int>(nb_atoms_to_read_)); // number of atoms in the PDB record matches the frame
00153         xdrfile_read_int(&step,1,input_file_); // reads the step number
00154         xdrfile_read_float(&time,1,input_file_);
00155         xdrfile_read_float(box,9,input_file_); // reads the box dimensions
00156         result = xdrfile_decompress_coord_float(xyz,&natoms,&prec,input_file_); //reads the coordinates in xyz
00157         assert(result != 0);
00158         
00159         result=xdrfile_read_int(&magic,1,input_file_);
00160         if (result==0){
00161           if (current_frame_ <= first_frame_id_ - 1){
00162             std::cerr << "Starting frame id is greater than the number of frames in the provided file" << std::endl;
00163             exit(EXIT_FAILURE);
00164           }
00165           xdrfile_close(input_file_);
00166           input_file_=NULL;
00167         }
00168         assert (result==0 || magic==1995); //checks XDR magic number
00169       }
00170       while( current_frame_ < first_frame_id_ - 1 );
00171       
00172       //update the coordinates
00173       if (!is_init)
00174         for(typename Map_id_to_atom::iterator it_sel= selected_atoms_.begin(); it_sel!=selected_atoms_.end();++it_sel){
00175           unsigned i=it_sel->first;
00176           typename System::Atom::Point_3 new_center(
00177             xyz[3*(i-1)]*10, 
00178             xyz[3*(i-1)+1]*10,
00179             xyz[3*(i-1)+2]*10
00180           );//*10 because gromacs is in nanometer
00181 
00182           static_cast<typename System::Atom::Point_3&>(*it_sel->second)=new_center;
00183         }
00184       return boost::make_tuple(true,time,step);
00185     }
00186     
00188     bool has_more_frames(){
00189       return (input_file_!=NULL && current_frame_ !=last_frame_id_);
00190     }
00191     
00192     const unsigned& current_frame_id(){return current_frame_;}
00193   };
00194   
00195 }//namespace ESBTL
00196 
00197 
00198 
00199 
00200 
00201 
00202 
00203 
00204 
00205 
00206 
00207 
00208 
00209 
00210 
00211 
00212 
00213 
00214 #endif //SYSTEM_UPDATER_FROM_XDRFILE_H
00215