PSCalib/src/CalibFileFinder.cpp

Go to the documentation of this file.
00001 //--------------------------------------------------------------------------
00002 // File and Version Information:
00003 //      $Id$
00004 //
00005 // Description:
00006 //      Class CalibFileFinder...
00007 //
00008 // Author List:
00009 //      Mikhail S. Dubrovin
00010 //
00011 //------------------------------------------------------------------------
00012 
00013 //-----------------------
00014 // This Class's Header --
00015 //-----------------------
00016 #include "PSCalib/CalibFileFinder.h"
00017 
00018 //-----------------
00019 // C/C++ Headers --
00020 //-----------------
00021 #include <algorithm>
00022 #include <limits>
00023 #include <iostream>
00024 #include <stdexcept>
00025 #include <boost/filesystem.hpp>
00026 #include <boost/lexical_cast.hpp>
00027 
00028 //-------------------------------
00029 // Collaborating Class Headers --
00030 //-------------------------------
00031 #include "MsgLogger/MsgLogger.h"
00032 #include "pdsdata/xtc/DetInfo.hh"
00033 #include "PSCalib/Exceptions.h"
00034 
00035 //-----------------------------------------------------------------------
00036 // Local Macros, Typedefs, Structures, Unions and Forward Declarations --
00037 //-----------------------------------------------------------------------
00038 
00039 namespace fs = boost::filesystem;
00040 
00041 namespace {
00042 
00043   const char logger[] = "CalibFileFinder";
00044   
00045   // helper class for ordering files in a directory
00046   class CalibFile {
00047   public:
00048     CalibFile(const fs::path& path) 
00049       : m_path(path)
00050     {
00051       std::string basename = path.stem().string();
00052       std::string::size_type p = basename.find('-');
00053       if (p == std::string::npos) { 
00054         throw std::runtime_error("missing dash in filename: " + path.string());
00055       }
00056       
00057       std::string beginstr(basename, 0, p);
00058       std::string endstr(basename, p+1);
00059       
00060       m_begin = boost::lexical_cast<unsigned>(beginstr);
00061       if (endstr == "end") {
00062         m_end = std::numeric_limits<unsigned>::max();
00063       } else {
00064         m_end = boost::lexical_cast<unsigned>(endstr);
00065       }      
00066     }
00067     
00068     const fs::path path() const { return m_path; }
00069     unsigned begin() const { return m_begin; }
00070     unsigned end() const { return m_end; }
00071 
00072     // comparison for sorting
00073     bool operator<(const CalibFile& other) const {
00074       if (m_begin != other.m_begin) return m_begin < other.m_begin;
00075       return m_end > other.m_end;
00076     }
00077     
00078   private:
00079     fs::path m_path;
00080     unsigned m_begin;
00081     unsigned m_end;
00082   };
00083   
00084   std::ostream& operator<<(std::ostream& out, const CalibFile& cf) {
00085     return out << "CalibFile(\"" << cf.path() << "\", " << cf.begin() << ", " << cf.end() << ")" ;
00086   }
00087   
00088 
00089   // convert source address to string
00090   std::string toString( const Pds::Src& src )
00091   {
00092     if ( src.level() != Pds::Level::Source ) {
00093       throw PSCalib::NotDetInfoError(ERR_LOC);
00094     }
00095 
00096     const Pds::DetInfo& info = static_cast<const Pds::DetInfo&>( src ) ;
00097     std::ostringstream str ;
00098     str << Pds::DetInfo::name(info.detector()) << '.' << info.detId()
00099         << ':' << Pds::DetInfo::name(info.device()) << '.' << info.devId() ;
00100     return str.str() ;
00101   }
00102 
00103 }
00104 
00105 
00106 //----------------------------------------
00107 //-- Public Function Member Definitions --
00108 //----------------------------------------
00109 
00110 namespace PSCalib {
00111 
00112 //----------------
00113 // Constructors --
00114 //----------------
00115 
00116 CalibFileFinder::CalibFileFinder (const std::string& calibDir,
00117                                   const std::string& typeGroupName,
00118                                   const unsigned&    print_bits)
00119   : m_calibDir(calibDir)
00120   , m_typeGroupName(typeGroupName)
00121   , m_print_bits(print_bits)
00122 {
00123 }
00124 
00125 //--------------
00126 // Destructor --
00127 //--------------
00128 CalibFileFinder::~CalibFileFinder ()
00129 {
00130 }
00131 
00132 // If source name has DetInfo(...) - remove it, ex: "DetInfo(Camp.0:pnCCD.0)" -> "Camp.0:pnCCD.0"
00133 std::string
00134 CalibFileFinder::trancateSourceName(const std::string& str)
00135 {
00136   size_t pL = str.find('(');  
00137   size_t pR = str.find(')', pL+1);  
00138   return (pL != std::string::npos) ? std::string(str, pL+1, pR-pL-1) : str;
00139 }
00140 
00141 
00142 // find calibration file
00143 std::string
00144 CalibFileFinder::findCalibFile(const std::string& src, const std::string& dataType, unsigned long runNumber) const
00145 try {
00146   // if no directory given then don't do anything
00147   if ( m_calibDir == "" ) return std::string();
00148 
00149   // construct full path name
00150   fs::path dir = m_calibDir;
00151   dir /= m_typeGroupName;
00152   dir /= trancateSourceName(src);
00153   dir /= dataType;
00154 
00155   // scan directory
00156   std::vector<std::string> files;
00157   typedef fs::directory_iterator dir_iter;
00158   for (dir_iter diriter = dir_iter(dir); diriter != dir_iter(); ++ diriter ) {
00159     const fs::path& path = diriter->path();
00160     files.push_back(path.string());
00161   }
00162 
00163   return selectCalibFile(files, runNumber, m_print_bits);
00164 
00165 } catch (const fs::filesystem_error& ex) {
00166   // means cannot read directory
00167   return std::string();  
00168 }
00169 
00170 // find calibration file
00171 std::string
00172 CalibFileFinder::findCalibFile(const Pds::Src& src, const std::string& dataType, unsigned long runNumber) const
00173 {
00174   return findCalibFile(::toString(src), dataType, runNumber);
00175 }
00176 
00177 // Selects calibration file from a list of file names.
00178 std::string
00179 CalibFileFinder::selectCalibFile(const std::vector<std::string>& files, unsigned long runNumber, unsigned print_bits)
00180 {
00181   // convert strings into sortable objects
00182   std::vector<CalibFile> calfiles;
00183   for (std::vector<std::string>::const_iterator iter = files.begin(); iter != files.end(); ++ iter) {
00184 
00185     const fs::path path(*iter);
00186 
00187     // Ignore HISTORY files
00188     if (path.stem().string() == "HISTORY") continue;
00189 
00190     // only take *.data files
00191     if (path.extension() != ".data") {
00192       if( print_bits & 1 ) MsgLog(logger, info, "skipping file with wrong extension: " + path.string());
00193       continue;
00194     }
00195 
00196     try {
00197       calfiles.push_back(CalibFile(path));
00198     } catch (const std::exception& ex) {
00199       if( print_bits & 2 ) MsgLog(logger, warning, "skipping file: " + path.string() + ": " + ex.what());
00200     }
00201 
00202   }
00203 
00204   // find the last file in the list whose begin run is less or equal
00205   // to the run number
00206   std::sort(calfiles.begin(), calfiles.end());
00207   typedef std::vector<CalibFile>::const_reverse_iterator FileIter;
00208   for (FileIter it = calfiles.rbegin() ; it != calfiles.rend() ; ++ it ) {
00209     MsgLog(logger, debug, "trying: " << *it << " for run " << runNumber);
00210     if (it->begin() <= runNumber and runNumber <= it->end()) return it->path().string();
00211   }
00212   return std::string();
00213 }
00214 
00215 } // namespace PSCalib

Generated on 19 Dec 2016 for PSANAmodules by  doxygen 1.4.7