ImgAlgos/src/ImgRadialCorrection.cpp

Go to the documentation of this file.
00001 //--------------------------------------------------------------------------
00002 // File and Version Information:
00003 //      $Id$
00004 //
00005 // Description:
00006 //      Class ImgRadialCorrection...
00007 //
00008 // Author List:
00009 //      Mikhail S. Dubrovin
00010 //
00011 //------------------------------------------------------------------------
00012 
00013 //-----------------------
00014 // This Class's Header --
00015 //-----------------------
00016 #include "ImgAlgos/ImgRadialCorrection.h"
00017 
00018 //-----------------
00019 // C/C++ Headers --
00020 //-----------------
00021 #define _USE_MATH_DEFINES // for M_PI
00022 #include <cmath> // for sqrt, atan2
00023 //#include <math.h> // for exp, M_PI
00024 #include <fstream> // for ofstream
00025 
00026 //-------------------------------
00027 // Collaborating Class Headers --
00028 //-------------------------------
00029 #include "MsgLogger/MsgLogger.h"
00030 #include "psddl_psana/camera.ddl.h"
00031 #include "PSEvt/EventId.h"
00032 //#include "PSTime/Time.h"
00033 
00034 //-----------------------------------------------------------------------
00035 // Local Macros, Typedefs, Structures, Unions and Forward Declarations --
00036 //-----------------------------------------------------------------------
00037 #include <iomanip> // for setw, setfill
00038 #include <sstream> // for stringstream
00039 #include <iostream>// for setf
00040 
00041 // This declares this class as psana module
00042 using namespace std;
00043 using namespace ImgAlgos;
00044 PSANA_MODULE_FACTORY(ImgRadialCorrection)
00045 
00046 //              ----------------------------------------
00047 //              -- Public Function Member Definitions --
00048 //              ----------------------------------------
00049 
00050 namespace ImgAlgos {
00051 
00052 //----------------
00053 // Constructors --
00054 //----------------
00055 ImgRadialCorrection::ImgRadialCorrection (const std::string& name)
00056   : Module(name)
00057   , m_str_src()
00058   , m_inkey()
00059   , m_outkey()
00060   , m_xcenter()
00061   , m_ycenter()
00062   , m_rmin()
00063   , m_rmax()
00064   , m_rnbins()
00065   , m_phimin()
00066   , m_phimax()
00067   , m_pnbins()
00068   , m_event()   
00069   , m_print_bits()
00070   , m_count(0)
00071 {
00072   m_str_src    = configSrc("source",     "DetInfo()");
00073   m_inkey      = configStr("inkey",               ""); // default means raw data
00074   m_outkey     = configStr("outkey", "rad_corrected"); // "rc_Image2D" means corrected image as CSPadPixCoords::Image2D<double>
00075   m_xcenter    = config   ("xcenter",            850);
00076   m_ycenter    = config   ("ycenter",            850);
00077   m_rmin       = config   ("rmin",                10);
00078   m_rmax       = config   ("rmax",              1000);
00079   m_pnbins     = config   ("n_phi_bins",          12);
00080   m_event      = config   ("event",                0);
00081   m_print_bits = config   ("print_bits",           0);
00082 
00083   m_phimin   = -M_PI;
00084   m_phimax   =  M_PI;
00085   m_rnbins   =  unsigned(m_rmax - m_rmin); 
00086   m_rpsize   =  m_pnbins * m_rnbins;
00087 
00088   bookHistograms();
00089 }
00090 
00091 
00092 //--------------
00093 // Destructor --
00094 //--------------
00095 ImgRadialCorrection::~ImgRadialCorrection ()
00096 {
00097 }
00098 
00099 /// Method which is called once at the beginning of the job
00100 void 
00101 ImgRadialCorrection::beginJob(Event& evt, Env& env)
00102 {
00103   m_time = new TimeInterval();
00104 }
00105 
00106 /// Method which is called at the beginning of the run
00107 void 
00108 ImgRadialCorrection::beginRun(Event& evt, Env& env)
00109 {
00110   if( m_print_bits & 1 ) printInputParameters();
00111 }
00112 
00113 /// Method which is called at the beginning of the calibration cycle
00114 void 
00115 ImgRadialCorrection::beginCalibCycle(Event& evt, Env& env)
00116 {
00117 }
00118 
00119 /// Method which is called with event data, this is the only required 
00120 /// method, all other methods are optional
00121 void 
00122 ImgRadialCorrection::event(Event& evt, Env& env)
00123 {
00124   m_time -> startTimeOnce();
00125   ++ m_count;
00126 
00127   getAndProcImage(evt);
00128     //if ( getAndProcImage(evt) ) { ++ m_selected; return; } // if event is selected
00129     //else                        { skip();        return; } // if event is discarded
00130 }
00131   
00132 /// Method which is called at the end of the calibration cycle
00133 void 
00134 ImgRadialCorrection::endCalibCycle(Event& evt, Env& env)
00135 {
00136 }
00137 
00138 /// Method which is called at the end of the run
00139 void 
00140 ImgRadialCorrection::endRun(Event& evt, Env& env)
00141 {
00142 }
00143 
00144 /// Method which is called once at the end of the job
00145 void 
00146 ImgRadialCorrection::endJob(Event& evt, Env& env)
00147 {
00148   if( m_print_bits & 2 ) {
00149     MsgLog(name(), info, "Total number of events processed: " << m_count);
00150     m_time -> stopTime(m_count);
00151   }
00152 }
00153 
00154 //--------------------
00155 //--------------------
00156 //--------------------
00157 //--------------------
00158 
00159 // Print input parameters
00160 void 
00161 ImgRadialCorrection::printInputParameters()
00162 {
00163   WithMsgLog(name(), info, log) {
00164     log << "\n Input parameters:"
00165         << "\n source     : " << m_str_src
00166         << "\n inkey      : " << m_inkey      
00167         << "\n outkey     : " << m_outkey      
00168         << "\n xcenter    : " << m_xcenter
00169         << "\n ycenter    : " << m_ycenter
00170         << "\n rmin       : " << m_rmin   
00171         << "\n rmax       : " << m_rmax   
00172         << "\n event      : " << m_event   
00173         << "\n print_bits : " << m_print_bits;
00174   }
00175 }
00176 
00177 //--------------------
00178 
00179 bool
00180 ImgRadialCorrection::getAndProcImage(Event& evt)
00181 {
00182   //MsgLog(name(), info, "::getAndProcImage(...)");
00183 
00184   shared_ptr< CSPadPixCoords::Image2D<double> > img2d = evt.get(m_str_src, m_inkey, &m_src); 
00185   if (img2d.get()) {
00186     if( m_print_bits & 8 ) MsgLog(name(), info, "getAndProcImage(...): Get image as Image2D<double>");
00187     m_img2d = img2d.get();
00188     const unsigned shape[] = {(unsigned)m_img2d->getNRows(), (unsigned)m_img2d->getNCols()};
00189     m_ndarr = new ndarray<const double,2>(m_img2d->data(), shape);
00190     return procImage(evt);
00191   }
00192 
00193   shared_ptr< ndarray<const double,2> > img = evt.get(m_str_src, m_inkey, &m_src);
00194   if (img.get()) {
00195     if( m_print_bits & 8 ) MsgLog(name(), info, "getAndProcImage(...): Get image as ndarray<double,2>");
00196     m_img2d = new CSPadPixCoords::Image2D<double>(img->data(), img->shape()[0], img->shape()[1]);
00197     m_ndarr = img.get();
00198     return procImage(evt);
00199   }
00200 
00201   //shared_ptr<Psana::Camera::FrameV1> frmData = evt.get(m_source);
00202   shared_ptr<Psana::Camera::FrameV1> frmData = evt.get(m_str_src, "", &m_src);
00203   if (frmData.get()) {
00204 
00205     //unsigned h      = frmData->height();
00206     //unsigned w      = frmData->width();
00207     int offset = frmData->offset();
00208 
00209     //m_data = new double [h*w];
00210     double *p_data = &m_data_arr[0];
00211     unsigned ind = 0;
00212 
00213       const ndarray<const uint8_t, 2>& data8 = frmData->data8();
00214       if (not data8.empty()) {
00215         if( m_print_bits & 8 ) MsgLog(name(), info, "getAndProcImage(...): Get image as ndarray<const uint8_t,2>");
00216         const unsigned *shape = data8.shape();
00217         ndarray<const uint8_t, 2>::iterator cit;
00218         for(cit=data8.begin(); cit!=data8.end(); cit++) { p_data[ind++] = double(int(*cit) - offset); }
00219 
00220         m_ndarr = new ndarray<const double,2>(p_data, shape);
00221         m_img2d = new CSPadPixCoords::Image2D<double>(p_data, shape[0], shape[1]);
00222         return procImage(evt);
00223       }
00224 
00225       const ndarray<const uint16_t, 2>& data16 = frmData->data16();
00226       if (not data16.empty()) {
00227         if( m_print_bits & 8 ) MsgLog(name(), info, "getAndProcImage(...): Get image as ndarray<const uint16_t,2>");
00228         const unsigned *shape = data16.shape();
00229         ndarray<const uint16_t, 2>::iterator cit;
00230         // This loop consumes ~5 ms/event for Opal1000 camera with 1024x1024 image size 
00231         for(cit=data16.begin(); cit!=data16.end(); cit++) { p_data[ind++] = double(*cit) - offset; }
00232 
00233         m_ndarr = new ndarray<const double,2>(p_data, shape);
00234         m_img2d = new CSPadPixCoords::Image2D<double>(p_data, shape[0], shape[1]);
00235         return procImage(evt);
00236       }
00237   }
00238 
00239     return false; // if the image object is not found in evt
00240 }
00241 
00242 //--------------------
00243 
00244 bool
00245 ImgRadialCorrection::procImage(Event& evt)
00246 {
00247   if( m_print_bits & 4 )   printEventId(evt);
00248   if( m_count == 1 )       initPixGeometry();
00249                            resetHistograms();
00250                            accumulateHistograms();
00251                            normalizeHistograms();
00252   if( m_count == m_event ) saveHistograms();
00253                            applyRadialCorrection();
00254   if( m_count == m_event ) saveCorrectedImage();
00255                            add_corrected_img_in_event(evt);
00256   return true;
00257 }
00258 
00259 //--------------------
00260 
00261 //inline
00262 unsigned
00263 ImgRadialCorrection::index_for_value(double v, double vmin, double vmax, unsigned nbins)
00264 {
00265   if( v <  vmin ) return 0;
00266   if( v >= vmax ) return nbins-1;
00267   return unsigned( double(nbins) * (v-vmin) / (vmax-vmin) );
00268 }
00269 
00270 //--------------------
00271 
00272 inline
00273 unsigned
00274 ImgRadialCorrection::get_img_index(unsigned r, unsigned c)
00275 {
00276   return r*m_ncols + c;
00277 }
00278 
00279 //--------------------
00280 
00281 void 
00282 ImgRadialCorrection::bookHistograms()
00283 {
00284   m_rp_amp = new double  [m_rnbins * m_pnbins];
00285   m_rp_sta = new unsigned[m_rnbins * m_pnbins];
00286   m_r_amp  = new double  [m_rnbins];  
00287   m_r_sta  = new unsigned[m_rnbins];  
00288 }
00289 
00290 //--------------------
00291 
00292 void 
00293 ImgRadialCorrection::resetHistograms()
00294 {
00295   for (unsigned ir=0; ir<m_rnbins; ir++) {
00296       m_r_amp[ir] = 0;  
00297       m_r_sta[ir] = 0;  
00298   }
00299   
00300   for (unsigned irp=0; irp<m_rpsize; irp++) {
00301       m_rp_amp[irp]=0;
00302       m_rp_sta[irp]=0;
00303   }
00304 }
00305 
00306 //--------------------
00307 
00308 void 
00309 ImgRadialCorrection::initPixGeometry()
00310 {
00311   m_nrows = m_ndarr->shape()[0];
00312   m_ncols = m_ndarr->shape()[1];
00313   // cout << "Shape:" << m_nrows << " x " << m_ncols << endl; 
00314 
00315   m_radval = new double   [m_nrows * m_ncols];
00316   m_phival = new double   [m_nrows * m_ncols];
00317   m_radind = new unsigned [m_nrows * m_ncols];
00318   m_phiind = new unsigned [m_nrows * m_ncols];
00319 
00320   for(uint16_t r=0; r<m_nrows; r++) {
00321     double dy = r - m_ycenter;
00322     for(uint16_t c=0; c<m_ncols; c++) {
00323       double dx = c - m_xcenter;
00324       int ind = get_img_index(r,c);
00325       m_radval[ind] = std::sqrt(dx*dx+dy*dy);
00326       m_phival[ind] = std::atan2(dy,dx);
00327       m_radind[ind] = index_for_value(m_radval[ind], m_rmin,   m_rmax,   m_rnbins);
00328       m_phiind[ind] = index_for_value(m_phival[ind], m_phimin, m_phimax, m_pnbins);
00329 
00330       //cout << m_radind[ind] << " "
00331       //     << m_phiind[ind] << " : ";
00332     }
00333     // cout << endl;
00334   }
00335 }
00336 
00337 //--------------------
00338 
00339 void 
00340 ImgRadialCorrection::accumulateHistograms()
00341 {
00342   ndarray<const double,2> &amparr = *m_ndarr;
00343 
00344   for(uint16_t r=0; r<m_nrows; r++){
00345     for(uint16_t c=0; c<m_ncols; c++){
00346 
00347       double amp  = amparr[r][c];
00348       int    ind  = get_img_index(r,c);
00349       int    irad = m_radind[ind];
00350       int    iphi = m_phiind[ind];
00351 
00352       m_rp_amp[iphi*m_rnbins+irad] += amp;
00353       m_rp_sta[iphi*m_rnbins+irad] ++;    
00354       m_r_amp[irad]                += amp;
00355       m_r_sta[irad]                ++;
00356     }
00357   }
00358 }
00359 
00360 //--------------------
00361 
00362 void 
00363 ImgRadialCorrection::normalizeHistograms()
00364 {
00365   for (unsigned ir=0; ir<m_rnbins; ir++) {
00366     m_r_amp[ir] = (m_r_sta[ir] > 0)? m_r_amp[ir] / m_r_sta[ir] : 0;  
00367   }
00368   
00369   for (unsigned irp=0; irp<m_rpsize; irp++) {
00370     m_rp_amp[irp]= (m_rp_sta[irp] > 0)? m_rp_amp[irp] / m_rp_sta[irp] : 0;
00371   }
00372 
00373   // Add the m_r_amp histogram as the 1st bin of m_rp_amp[...]
00374   //unsigned ip=0;
00375   //for (unsigned ir=0; ir<m_rnbins; ir++) {
00376   //  m_rp_amp[ip*m_rnbins+ir] = m_r_amp[ir]; 
00377   //}
00378 }
00379 
00380 //--------------------
00381 
00382 void 
00383 ImgRadialCorrection::saveHistograms()
00384 {
00385   //CSPadPixCoords::Image2D<double> *arr2d =  new CSPadPixCoords::Image2D<double>(m_rp_amp, m_pnbins, m_rnbins);
00386   //arr2d -> saveImageInFile("r-phi-arr2d.txt",3);
00387 
00388   string fname; fname="r-phi-arr2d-ev" + stringEventN() + ".txt";
00389   ofstream file(fname.c_str(),ios_base::out);
00390 
00391   for (unsigned ir=0; ir<m_rnbins; ir++) {
00392     for (unsigned ip=0; ip<m_pnbins; ip++) {
00393 
00394       file << m_rp_amp[ip*m_rnbins+ir] << "  "; 
00395     }
00396       file << endl;
00397   }
00398 
00399   file.close();
00400 }
00401 
00402 //--------------------
00403 
00404 void 
00405 ImgRadialCorrection::applyRadialCorrection()
00406 {
00407   //double *p_data = &m_data_arr[0];
00408 
00409   ndarray<const double,2> &amparr = *m_ndarr;
00410 
00411   for(uint16_t r=0; r<m_nrows; r++){
00412     for(uint16_t c=0; c<m_ncols; c++){
00413 
00414       double amp  = amparr[r][c];
00415       int    ind  = get_img_index(r,c);
00416       int    irad = m_radind[ind];
00417       int    iphi = m_phiind[ind];
00418       double rad  = m_radval[ind];
00419       //double phi  = m_phival[ind];
00420 
00421       if (rad < m_rmin || rad > m_rmax || amp == 0) 
00422            m_data_arr[ind] = 0;
00423       else 
00424         //m_data_arr[ind] = amp - m_r_amp[irad];
00425           m_data_arr[ind] = amp - m_rp_amp[iphi*m_rnbins+irad];
00426     }
00427   }
00428 }
00429 
00430 //--------------------
00431 
00432 void 
00433 ImgRadialCorrection::saveCorrectedImage()
00434 {
00435   CSPadPixCoords::Image2D<double> *arr2d =  new CSPadPixCoords::Image2D<double>(m_data_arr, m_nrows, m_ncols);
00436   string fname; fname="img-r-corrected-ev" + stringEventN() + ".txt";
00437   arr2d -> saveImageInFile(fname,0);
00438 }
00439 
00440 //--------------------
00441 
00442 void 
00443 ImgRadialCorrection::printEventId(Event& evt)
00444 {
00445   shared_ptr<PSEvt::EventId> eventId = evt.get();
00446   if (eventId.get()) {
00447     //MsgLog( name(), info, "Event="  << m_count << " ID: " << *eventId);
00448     MsgLog( name(), info, "Event="  << m_count << " time: " << stringTimeStamp(evt) );
00449   }
00450 }
00451 
00452 ///--------------------
00453 
00454 std::string
00455 ImgRadialCorrection::stringTimeStamp(Event& evt)
00456 {
00457   shared_ptr<PSEvt::EventId> eventId = evt.get();
00458   if (eventId.get()) {
00459     return (eventId->time()).asStringFormat("%Y%m%dT%H:%M:%S%f"); //("%Y-%m-%d %H:%M:%S%f%z");
00460   }
00461   return std::string("Time-stamp-is-unavailable");
00462 }
00463 
00464 //--------------------
00465 
00466 string 
00467 ImgRadialCorrection::stringEventN()
00468 {
00469   stringstream ssEvNum; ssEvNum << setw(6) << setfill('0') << m_count;
00470   return ssEvNum.str();
00471 }
00472 
00473 //--------------------
00474 
00475 void
00476 ImgRadialCorrection::add_corrected_img_in_event(Event& evt)
00477 {
00478   if(m_outkey == "rc_Image2D") {
00479 
00480     shared_ptr< CSPadPixCoords::Image2D<double> > img2d( new CSPadPixCoords::Image2D<double>(m_data_arr, m_nrows, m_ncols) );
00481     evt.put(img2d, m_src, m_outkey);
00482 
00483   } else {
00484 
00485     const unsigned shape[] = {m_nrows, m_ncols};
00486     shared_ptr< ndarray<double,2> > img2d( new ndarray<double,2>(m_data_arr,shape) );
00487     evt.put(img2d, m_src, m_outkey);
00488   }
00489 }
00490 
00491 //--------------------
00492 //--------------------
00493 
00494 } // namespace ImgAlgos
00495 
00496 //---------EOF--------

Generated on 19 Dec 2016 for PSDMSoftware by  doxygen 1.4.7