00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #include "ImgAlgos/ImgRadialCorrection.h"
00017
00018
00019
00020
00021 #define _USE_MATH_DEFINES // for M_PI
00022 #include <cmath>
00023
00024 #include <fstream>
00025
00026
00027
00028
00029 #include "MsgLogger/MsgLogger.h"
00030 #include "psddl_psana/camera.ddl.h"
00031 #include "PSEvt/EventId.h"
00032
00033
00034
00035
00036
00037 #include <iomanip>
00038 #include <sstream>
00039 #include <iostream>
00040
00041
00042 using namespace std;
00043 using namespace ImgAlgos;
00044 PSANA_MODULE_FACTORY(ImgRadialCorrection)
00045
00046
00047
00048
00049
00050 namespace ImgAlgos {
00051
00052
00053
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", "");
00074 m_outkey = configStr("outkey", "rad_corrected");
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
00094
00095 ImgRadialCorrection::~ImgRadialCorrection ()
00096 {
00097 }
00098
00099
00100 void
00101 ImgRadialCorrection::beginJob(Event& evt, Env& env)
00102 {
00103 m_time = new TimeInterval();
00104 }
00105
00106
00107 void
00108 ImgRadialCorrection::beginRun(Event& evt, Env& env)
00109 {
00110 if( m_print_bits & 1 ) printInputParameters();
00111 }
00112
00113
00114 void
00115 ImgRadialCorrection::beginCalibCycle(Event& evt, Env& env)
00116 {
00117 }
00118
00119
00120
00121 void
00122 ImgRadialCorrection::event(Event& evt, Env& env)
00123 {
00124 m_time -> startTimeOnce();
00125 ++ m_count;
00126
00127 getAndProcImage(evt);
00128
00129
00130 }
00131
00132
00133 void
00134 ImgRadialCorrection::endCalibCycle(Event& evt, Env& env)
00135 {
00136 }
00137
00138
00139 void
00140 ImgRadialCorrection::endRun(Event& evt, Env& env)
00141 {
00142 }
00143
00144
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
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
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
00202 shared_ptr<Psana::Camera::FrameV1> frmData = evt.get(m_str_src, "", &m_src);
00203 if (frmData.get()) {
00204
00205
00206
00207 int offset = frmData->offset();
00208
00209
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
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;
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
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
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
00331
00332 }
00333
00334 }
00335 }
00336
00337
00338
00339 void
00340 ImgRadialCorrection::accumulateHistograms()
00341 {
00342 ndarray<const double,2> &arr = *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
00374
00375
00376
00377
00378 }
00379
00380
00381
00382 void
00383 ImgRadialCorrection::saveHistograms()
00384 {
00385
00386
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
00408
00409 ndarray<const double,2> &arr = *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
00420
00421 if (rad < m_rmin || rad > m_rmax || amp == 0)
00422 m_data_arr[ind] = 0;
00423 else
00424
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
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");
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 }
00495
00496