pdscalibdata/src/NDArrIOV1.cpp

Go to the documentation of this file.
00001 //--------------------------------------------------------------------------
00002 // File and Version Information:
00003 //      $Id: NDArrIOV1.cpp 12297 2016-07-20 00:10:06Z dubrovin@SLAC.STANFORD.EDU $
00004 //      $Revision: 12297 $
00005 //
00006 // Author: Mikhail Dubrovin
00007 //------------------------------------------------------------------------
00008 
00009 //-----------------------
00010 // This Class's Header --
00011 //-----------------------
00012 #include "pdscalibdata/NDArrIOV1.h"
00013 
00014 //-----------------
00015 // C/C++ Headers --
00016 //-----------------
00017 #include <algorithm>
00018 #include <stdexcept>
00019 #include <fstream>
00020 #include <sstream>   // for stringstream
00021 #include <stdlib.h>  // for atoi
00022 #include <cstring>   // for memcpy
00023 #include <stdint.h>  // uint8_t, uint32_t, etc.
00024 
00025 //-------------------------------
00026 // Collaborating Class Headers --
00027 //-------------------------------
00028 #include "MsgLogger/MsgLogger.h"
00029 
00030 namespace pdscalibdata {
00031 
00032 //-----------------------------
00033 
00034 template <typename TDATA, unsigned NDIM>
00035 NDArrIOV1<TDATA, NDIM>::NDArrIOV1 ( const std::string& fname
00036                                   , const unsigned print_bits ) 
00037   : p_nda(0)
00038   , m_fname(fname)
00039   , m_val_def(0)
00040   , m_nda_def(ndarray<const TDATA, NDIM>())
00041   , m_print_bits(print_bits)
00042   , m_ctor(0)
00043 {
00044   init();
00045   m_size = 0; // actual size is loaded from metadata
00046 }
00047 
00048 //-----------------------------
00049 
00050 template <typename TDATA, unsigned NDIM>
00051 NDArrIOV1<TDATA, NDIM>::NDArrIOV1 ( const std::string& fname
00052                                   , const shape_t* shape_def
00053                                   , const TDATA& val_def 
00054                                   , const unsigned print_bits ) 
00055   : p_nda(0)
00056   , m_fname(fname)
00057   , m_val_def(val_def)
00058   , m_nda_def(ndarray<const TDATA, NDIM>())
00059   , m_print_bits(print_bits)
00060   , m_ctor(1)
00061 {
00062   init();
00063   std::memcpy (&m_shape[0], shape_def, c_ndim*sizeof(shape_t));  
00064   //for(unsigned i=0; i<c_ndim; ++i) m_shape[i] = shape_def[i];
00065   //cout << "TIOV1: shape_def : [" << shape_def[0] << "," << shape_def[1] << "]\n";
00066   //cout << "TIOV1: m_shape   : [" << m_shape[0] << "," << m_shape[1] << "]\n";
00067 }
00068 
00069 //-----------------------------
00070 
00071 template <typename TDATA, unsigned NDIM>
00072 NDArrIOV1<TDATA, NDIM>::NDArrIOV1 ( const std::string& fname
00073                                   , const ndarray<const TDATA, NDIM>& nda_def
00074                                   , const unsigned print_bits ) 
00075   : p_nda(0)
00076   , m_fname(fname)
00077   , m_val_def(0)
00078   , m_nda_def(nda_def)
00079   , m_print_bits(print_bits)
00080   , m_ctor(2)
00081 {
00082   init();
00083   m_size = nda_def.size();
00084   std::memcpy (&m_shape[0], nda_def.shape(), c_ndim*sizeof(shape_t));  
00085   //std::cout << "XXX m_nda_def in c-tor 2: " << m_nda_def << '\n';
00086 }
00087 
00088 //-----------------------------
00089 
00090 template <typename TDATA, unsigned NDIM>
00091 NDArrIOV1<TDATA, NDIM>::~NDArrIOV1()
00092 {
00093   if(m_print_bits & 2) MsgLog(__name__(), info, "DESTRUCTOR is called for ctor:" << m_ctor << ", fname=" << m_fname);
00094   delete p_nda;
00095 }
00096 
00097 //-----------------------------
00098 
00099 template <typename TDATA, unsigned NDIM>
00100 void NDArrIOV1<TDATA, NDIM>::init()
00101 {
00102   if( m_print_bits & 2 ) {
00103     MsgLog(__name__(), info, "ctor:" << m_ctor << ", fname=" << m_fname);
00104     print();
00105   }
00106   m_status = NDArrIOV1<TDATA, NDIM>::UNDEFINED;
00107 }
00108 
00109 //-----------------------------
00110 
00111 template <typename TDATA, unsigned NDIM>
00112 void NDArrIOV1<TDATA, NDIM>::load_ndarray()
00113 {
00114     // if file is not available - create default ndarray
00115     if ((!file_is_available()) && m_ctor>0) { 
00116         if( m_print_bits & 4 ) MsgLog(__name__(), warning, "Use default calibration parameters.");
00117         create_ndarray(true);
00118         m_status = NDArrIOV1<TDATA, NDIM>::DEFAULT; // std::string("used default");
00119         return; 
00120     }
00121 
00122     if( m_print_bits & 1 ) MsgLog(__name__(), info, "Load file \"" << m_fname << "\"");
00123 
00124     m_count_str_data = 0;
00125     m_count_str_comt = 0;
00126     m_count_data     = 0;
00127 
00128     // open file
00129     std::ifstream in(m_fname.c_str());
00130     if (not in.good()) { 
00131         if(m_print_bits) MsgLog(__name__(), error, "Failed to open file: \"" + m_fname + "\""); 
00132         m_status = NDArrIOV1<TDATA, NDIM>::UNREADABLE; // std::string("file is unreadable");
00133         return;
00134     }
00135   
00136     // read and process all strings
00137     std::string str; 
00138     while(getline(in,str)) {
00139         // cout << str << '\n';
00140 
00141         // 1. parse lines with comments marked by # in the 1st position
00142         if(str[0] == '#') parse_str_of_comment(str.substr(1));
00143 
00144         // 2. skip empty lines 
00145         else if (str.find_first_not_of(" ")==string::npos) continue; 
00146 
00147         // 3. parse 1st line and load other data
00148         else load_data(in,str);
00149     }
00150 
00151     //close file
00152     in.close();
00153     m_status = NDArrIOV1<TDATA, NDIM>::LOADED; // std::string("loaded from file");
00154 }
00155 
00156 //-----------------------------
00157 
00158 template <typename TDATA, unsigned NDIM>
00159 std::string NDArrIOV1<TDATA, NDIM>::str_status()
00160 {
00161   if      (m_status == NDArrIOV1<TDATA, NDIM>::LOADED)     return std::string("loaded from file");
00162   else if (m_status == NDArrIOV1<TDATA, NDIM>::DEFAULT)    return std::string("used default");
00163   else if (m_status == NDArrIOV1<TDATA, NDIM>::UNREADABLE) return std::string("file is unreadable");
00164   else if (m_status == NDArrIOV1<TDATA, NDIM>::UNDEFINED)  return std::string("undefined...");
00165   else                                                     return std::string("unknown...");
00166 }
00167 
00168 //-----------------------------
00169 
00170 template <typename TDATA, unsigned NDIM>
00171 bool NDArrIOV1<TDATA, NDIM>::file_is_available()
00172 {
00173   if(m_fname.empty()) {
00174     if( m_print_bits & 4 ) MsgLog(__name__(), warning, "File name IS EMPTY!");
00175     return false;
00176   }
00177 
00178   std::ifstream file(m_fname.c_str());
00179   if(!file.good()) {
00180     if( m_print_bits & 8 ) MsgLog(__name__(), warning, "File: " << m_fname << " DOES NOT EXIST!");
00181     return false;
00182   }
00183   file.close();
00184   return true;  
00185 }
00186 
00187 //-----------------------------
00188 
00189 template <typename TDATA, unsigned NDIM>
00190 void NDArrIOV1<TDATA, NDIM>::parse_str_of_comment(const std::string& str)
00191 {
00192     m_count_str_comt ++;
00193     // cout << "comment, str.size()=" << str.size() << '\n';
00194 
00195     std::string field;
00196     std::stringstream ss(str);
00197 
00198     ss >> field;
00199 
00200     if (field=="DTYPE") { 
00201       ss >> m_str_type;
00202       m_enum_type = enumDataTypeForString(m_str_type);
00203 
00204       if( m_print_bits & 32 )
00205         if (m_enum_type != enumDataType<TDATA>()) {
00206           std::stringstream smsg; 
00207           smsg << "(enum) DTYPE in file metadata (" << strDataTypeForEnum(m_enum_type)
00208                << ") is different from expected (" << strDataTypeForEnum(enumDataType<TDATA>()) << ")";
00209           MsgLog(__name__(), warning, smsg.str());
00210         }
00211     }
00212 
00213     else if (field=="NDIM") {
00214       ss >> m_ndim;
00215       if (m_ndim != ndim()) {   
00216         std::stringstream smsg; 
00217         smsg << "NDIM in file metadata: " << m_ndim 
00218              << " is different from declaration: " << ndim();
00219         MsgLog(__name__(), warning, smsg.str());
00220         //throw std::runtime_error(smsg.str());
00221       }
00222     }
00223 
00224     else if (field.substr(0,4)=="DIM:") { 
00225         //cout << "field.substr(0,4)" << field.substr(0,4) << "field[4]" << field[4] << endl;
00226         int dim = atoi(&field[4]); 
00227         shape_t val;    
00228         ss >> val;
00229 
00230         if (m_ctor == 0) { // get ndarray shape and size from metadata
00231             m_shape[dim] = val;
00232             m_size *= val;
00233             // cout << "Current m_size = " << m_size << '\n';
00234         }
00235         else if (m_shape[dim] !=val) { // check that metadata is consistent with expected
00236            std::stringstream smsg; 
00237            smsg << "NDArray metadata shape field " << field
00238                 << " = " << val 
00239                 << " is different from expected " << m_shape[dim] 
00240                 << " in file " << m_fname
00241                 << "\nCheck that calibration file has expected shape and data...";
00242            MsgLog(__name__(), warning, smsg.str());
00243            //throw std::runtime_error(smsg.str());
00244         }
00245     }
00246 
00247     else 
00248       //MsgLog(__name__(), info, "Ignore comment: " << str );
00249       return;
00250 }
00251 
00252 //-----------------------------
00253 
00254 template <typename TDATA, unsigned NDIM>
00255 void NDArrIOV1<TDATA, NDIM>::create_ndarray(const bool& fill_def)
00256 {
00257     if (p_nda) delete p_nda; // prevent memory leak
00258     // shape should already be available for
00259     // m_ctor = 0 - from parsing input file header,
00260     // m_ctor = 1,2 - from input pars
00261     p_nda = new ndarray<TDATA, NDIM>(m_shape);
00262     p_data = p_nda->data();
00263     m_size = p_nda->size();
00264 
00265     if (m_ctor>0 && fill_def) {
00266       if      (m_ctor==2) std::memcpy (p_data, m_nda_def.data(), m_size*sizeof(TDATA));
00267       else if (m_ctor==1) std::fill_n (p_data, m_size, m_val_def);
00268       else return; // There is no default initialization for ctor=0 w/o shape
00269     }    
00270     if( m_print_bits & 16 ) MsgLog(__name__(), info, "Created ndarray of the shape=(" << str_shape() << ")");
00271     if( m_print_bits & 32 ) MsgLog(__name__(), info, "Created ndarray: " << *p_nda);
00272 }
00273 
00274 //-----------------------------
00275 
00276 template <typename TDATA, unsigned NDIM>
00277 void NDArrIOV1<TDATA, NDIM>::load_data(std::ifstream& in, const std::string& str)
00278 {
00279     if (! m_count_str_data++) create_ndarray();
00280 
00281     // parse the 1st string
00282     TDATA val;
00283     TDATA* it=p_data; 
00284 
00285     std::stringstream ss(str);
00286     while (ss >> val and m_count_data != m_size) { 
00287       *it++ = val;
00288       ++m_count_data;
00289       //if( ndim()==1 ) cout << "count:data = " << m_count_data << " : " << val << '\n';
00290     }
00291 
00292     // load all data by the end
00293     while(in >> val and m_count_data != m_size) {
00294       *it++ = val;
00295       ++m_count_data;
00296       //if( ndim()==1 ) cout << "count:data = " << m_count_data << " : " << val << '\n';
00297     }
00298 
00299     // check that we read whole array
00300     if (m_count_data != m_size) {
00301       std::stringstream ss;
00302       ss << "NDArray file:\n  " << m_fname << "\n  does not have enough data: "
00303          << "read " << m_count_data << " numbers, expecting " << m_size;
00304       // MsgLog(__name__(), warning, ss.str());
00305       if( ndim()>1 ) throw std::runtime_error(ss.str());
00306     }
00307 
00308     // and no data left after we finished reading
00309     if ( in >> val ) {
00310       ++ m_count_data;
00311       std::stringstream ss;
00312       ss << "NDArray file:\n  " << m_fname << "\n  has extra data: "
00313          << "read " << m_count_data << " numbers, expecting " << m_size; 
00314       MsgLog(__name__(), warning, ss.str());
00315       if( ndim()>1 ) throw std::runtime_error(ss.str());
00316     }
00317 }
00318 
00319 //-----------------------------
00320 
00321 template <typename TDATA, unsigned NDIM>
00322 //ndarray<const TDATA, NDIM>& 
00323 ndarray<TDATA, NDIM>& 
00324 NDArrIOV1<TDATA, NDIM>::get_ndarray(const std::string& fname)
00325 {
00326   if ( (!fname.empty()) && fname != m_fname) {
00327     m_fname = fname;
00328     load_ndarray(); 
00329   }
00330 
00331   if (!p_nda) load_ndarray();
00332   if (!p_nda) {
00333     if(m_print_bits) MsgLog(__name__(), error, "ndarray IS NOT LOADED! Check file: \"" << m_fname <<"\"");
00334     return m_nda_empty;
00335   }
00336   //std::cout << "TEST in get_ndarray(...):";
00337   //if (p_nda) std::cout << *p_nda << '\n';
00338 
00339   return *p_nda;
00340 }
00341 
00342 //-----------------------------
00343 
00344 template <typename TDATA, unsigned NDIM>
00345 void NDArrIOV1<TDATA, NDIM>::print()
00346 {
00347     std::stringstream ss; 
00348     ss << "print()"
00349        << "\n  Constructor          # " << m_ctor
00350        << "\n  Number of dimensions : " << ndim()
00351        << "\n  Data type and size   : " << strOfDataTypeAndSize<TDATA>()
00352        << "\n  Enumerated data type : " << enumDataType<TDATA>()
00353        << "\n  String data type     : " << strDataType<TDATA>()
00354        << '\n';
00355     MsgLog(__name__(), info, ss.str());
00356 }
00357 
00358 //-----------------------------
00359 
00360 template <typename TDATA, unsigned NDIM>
00361 void NDArrIOV1<TDATA, NDIM>::print_file()
00362 {
00363     if (! file_is_available() ) {
00364       MsgLog(__name__(), warning, "print_file() : file " << m_fname << " is not available!");
00365       return;
00366     }
00367 
00368     MsgLog(__name__(), info, "print_file()\nContent of the file: " << m_fname);
00369 
00370     // open file
00371     std::ifstream in(m_fname.c_str());
00372     if (not in.good()) { MsgLog(__name__(), error, "Failed to open file: "+m_fname); return; }
00373   
00374     // read and dump all fields
00375     //std::string s; while(in) { in >> s; cout << s << " "; }
00376 
00377     // read and dump all strings
00378     std::string str; 
00379     while(getline(in,str)) cout << str << '\n';
00380     cout << '\n';
00381     //close file
00382     in.close();
00383 }
00384 
00385 //-----------------------------
00386 
00387 template <typename TDATA, unsigned NDIM>
00388 void NDArrIOV1<TDATA, NDIM>::print_ndarray()
00389 {
00390     //const ndarray<const TDATA, NDIM> nda = get_ndarray();
00391     if (! p_nda) load_ndarray();
00392     if (! p_nda) return;
00393 
00394     std::stringstream smsg; 
00395     smsg << "Print ndarray<" << strDataType<TDATA>() 
00396          << "," << ndim()
00397          << "> of size=" << p_nda->size()
00398          << ":\n" << *p_nda;
00399     MsgLog(__name__(), info, smsg.str());
00400 }
00401 
00402 //-----------------------------
00403 
00404 template <typename TDATA, unsigned NDIM>
00405 std::string NDArrIOV1<TDATA, NDIM>::str_ndarray_info()
00406 {
00407   //const ndarray<const TDATA, NDIM>& nda = get_ndarray();
00408     if (! p_nda) load_ndarray();
00409     if (! p_nda) return std::string("ndarray is non-accessible...");
00410 
00411     std::stringstream smsg; 
00412     smsg << "ndarray<" << std::setw(8) << std::left << strDataType<TDATA>() 
00413          << "," << ndim()
00414          << "> of size=" << p_nda->size()
00415          << ":";
00416     TDATA* it = p_nda->data();
00417     for( unsigned i=0; i<min(size_t(10),p_nda->size()); i++ ) smsg << " " << *it++; smsg << " ...";
00418     //MsgLog(__name__(), info, smsg.str());
00419     return smsg.str();
00420 }
00421 
00422 //-----------------------------
00423 
00424 template <typename TDATA, unsigned NDIM>
00425 std::string NDArrIOV1<TDATA, NDIM>::str_shape()
00426 {
00427   std::stringstream smsg;
00428   for( unsigned i=0; i<ndim(); i++ ) {
00429     smsg << m_shape[i]; if (i<ndim()-1) smsg << ", ";
00430   }
00431   return smsg.str();
00432 }
00433 
00434 //-----------------------------
00435 
00436 template <typename TDATA, unsigned NDIM>
00437 void NDArrIOV1<TDATA, NDIM>::save_ndarray(const ndarray<const TDATA, NDIM>& nda, 
00438                                           const std::string& fname,
00439                                           const std::vector<std::string>& vcoms, 
00440                                           const unsigned& print_bits)
00441 {
00442     const unsigned ndim = NDIM;
00443     std::string str_dtype = strDataType<TDATA>();
00444     std::stringstream sstype; sstype << "ndarray<" << str_dtype 
00445                                      << "," << ndim << ">";
00446 
00447     if (print_bits & 1) {
00448         std::stringstream smsg; 
00449         smsg << "Save " << sstype.str()
00450              << " of size=" << nda.size()
00451              << " in file: " << fname;
00452         MsgLog(__name__(), info, smsg.str());
00453     }
00454 
00455     // open file
00456     std::ofstream out(fname.c_str());
00457     if (not out.good()) { 
00458        if(print_bits) MsgLog(__name__(), error, "Failed to open output file: " + fname); 
00459        return; 
00460     }
00461   
00462     // write comments if available
00463     if (!vcoms.empty()) {
00464       for(vector<string>::const_iterator it = vcoms.begin(); it != vcoms.end(); it++)
00465         out << "# " << *it << '\n';
00466       out << '\n';
00467     }
00468 
00469     // write permanent comments
00470     out << "# DATE_TIME  " << strTimeStamp() << '\n';
00471     out << "# AUTHOR     " << strEnvVar("LOGNAME") << '\n';
00472     out << '\n';
00473 
00474     // write metadata
00475     out << "# Metadata for " << sstype.str() << '\n';
00476     out << "# DTYPE    " << str_dtype << '\n';
00477     out << "# NDIM     " << ndim << '\n';
00478     //shape_t shape = nda.shape()
00479     for(unsigned i=0; i<ndim; i++) out << "# DIM:" << i << "    " << nda.shape()[i] << '\n';
00480     out << '\n';
00481 
00482     // save data
00483     unsigned nmax_in_line = (ndim>1) ? nda.shape()[ndim-1] : 10; 
00484     unsigned count_in_line=0; 
00485 
00486     typename ndarray<const TDATA, NDIM>::iterator it = nda.begin();
00487     for (; it!=nda.end(); ++it) {
00488       out << std::setw(10) << *it << " ";
00489       if( ++count_in_line < nmax_in_line) continue;
00490           count_in_line = 0;
00491           out << '\n';
00492     }
00493 
00494     //close file
00495     out.close();
00496 }
00497 
00498 //-----------------------------
00499 
00500 } // namespace pdscalibdata
00501 
00502 //-----------------------------
00503 //-----------------------------
00504 //-----------------------------
00505 
00506 template class pdscalibdata::NDArrIOV1<int,1>; 
00507 template class pdscalibdata::NDArrIOV1<unsigned,1>; 
00508 template class pdscalibdata::NDArrIOV1<unsigned short,1>; 
00509 template class pdscalibdata::NDArrIOV1<float,1>; 
00510 template class pdscalibdata::NDArrIOV1<double,1>; 
00511 template class pdscalibdata::NDArrIOV1<int16_t,1>; 
00512 template class pdscalibdata::NDArrIOV1<uint8_t,1>; 
00513 
00514 template class pdscalibdata::NDArrIOV1<int,2>; 
00515 template class pdscalibdata::NDArrIOV1<unsigned,2>; 
00516 template class pdscalibdata::NDArrIOV1<unsigned short,2>; 
00517 template class pdscalibdata::NDArrIOV1<float,2>; 
00518 template class pdscalibdata::NDArrIOV1<double,2>; 
00519 template class pdscalibdata::NDArrIOV1<int16_t,2>; 
00520 template class pdscalibdata::NDArrIOV1<uint8_t,2>; 
00521 
00522 template class pdscalibdata::NDArrIOV1<int,3>; 
00523 template class pdscalibdata::NDArrIOV1<unsigned,3>; 
00524 template class pdscalibdata::NDArrIOV1<unsigned short,3>; 
00525 template class pdscalibdata::NDArrIOV1<float,3>; 
00526 template class pdscalibdata::NDArrIOV1<double,3>; 
00527 template class pdscalibdata::NDArrIOV1<int16_t,3>; 
00528 template class pdscalibdata::NDArrIOV1<uint8_t,3>; 
00529 
00530 template class pdscalibdata::NDArrIOV1<int,4>; 
00531 template class pdscalibdata::NDArrIOV1<unsigned,4>; 
00532 template class pdscalibdata::NDArrIOV1<unsigned short,4>; 
00533 template class pdscalibdata::NDArrIOV1<float,4>; 
00534 template class pdscalibdata::NDArrIOV1<double,4>; 
00535 template class pdscalibdata::NDArrIOV1<int16_t,4>; 
00536 template class pdscalibdata::NDArrIOV1<uint8_t,4>; 
00537 
00538 template class pdscalibdata::NDArrIOV1<int,5>; 
00539 template class pdscalibdata::NDArrIOV1<unsigned,5>; 
00540 template class pdscalibdata::NDArrIOV1<unsigned short,5>; 
00541 template class pdscalibdata::NDArrIOV1<float,5>; 
00542 template class pdscalibdata::NDArrIOV1<double,5>; 
00543 template class pdscalibdata::NDArrIOV1<int16_t,5>; 
00544 template class pdscalibdata::NDArrIOV1<uint8_t,5>; 
00545 
00546 //-----------------------------
00547 //-----------------------------
00548 //-----------------------------

Generated on 19 Dec 2016 for PSDMSoftware by  doxygen 1.4.7