ImgAlgos/include/CommonMode.h

Go to the documentation of this file.
00001 #ifndef IMGALGOS_COMMONMODE_H
00002 #define IMGALGOS_COMMONMODE_H
00003 
00004 //--------------------------------------------------------------------------
00005 // File and Version Information:
00006 //      $Id: CommonMode.h 12980 2016-12-10 02:11:15Z cpo@SLAC.STANFORD.EDU $
00007 //
00008 // Description:
00009 //      Class CommonMode.
00010 //
00011 //------------------------------------------------------------------------
00012 
00013 //-----------------
00014 // C/C++ Headers --
00015 //-----------------
00016 
00017 #include <string>
00018 #include <vector>
00019 #include <fstream>   // ofstream
00020 #include <iomanip>   // for setw, setfill
00021 #include <sstream>   // for stringstream
00022 #include <stdint.h>  // uint8_t, uint32_t, etc.
00023 #include <iostream>
00024 #include <cmath>
00025 #include <algorithm> // for fill_n, std::sort
00026 
00027 //#include <cstring>   // for memcpy
00028 //#include <math.h>
00029 //#include <stdio.h>
00030 
00031 //----------------------
00032 // Base Class Headers --
00033 //----------------------
00034 
00035 //-------------------------------
00036 // Collaborating Class Headers --
00037 //-------------------------------
00038 
00039 #include "MsgLogger/MsgLogger.h"
00040 #include "ndarray/ndarray.h"
00041 
00042 namespace ImgAlgos {
00043 
00044 using namespace std;
00045 
00046 //--------------------
00047 typedef float work_t;
00048 
00049 //--------------------
00050 
00051 class SingleStore{
00052 public:
00053   static SingleStore* instance();
00054   void print();
00055   void make_ndarrays();
00056 
00057   // arrays for Epix100 common mode correction
00058   //const static unsigned shasd[2] = {704, 768};
00059   //const static unsigned shtrd[2] = {768, 704};
00060 
00061   ndarray<work_t,2> m_wasd; // (shasd); // work array shaped as data
00062   ndarray<work_t,2> m_wtrd; // (shtrd); // work array transposed from data
00063   ndarray<work_t,2> m_ctrd; // (shtrd); // array of corrected transposed data
00064  
00065 private:
00066 
00067   SingleStore() ;                 // !!!!! Private so that it can not be called from outside
00068   virtual ~SingleStore(){};
00069  
00070   static SingleStore* m_pInstance; // !!!!! Singleton instance
00071 
00072   // Copy constructor and assignment are disabled by default
00073   SingleStore (const SingleStore&) ;
00074   SingleStore& operator = (const SingleStore&) ;
00075 };
00076 
00077 //--------------------
00078 
00079  const static int UnknownCM = -10000; 
00080  const static unsigned ROWS2X1   = 185; 
00081  const static unsigned COLS2X1   = 388; 
00082  const static unsigned SIZE2X1   = ROWS2X1*COLS2X1; 
00083  const static unsigned COLSHALF  = COLS2X1/2;
00084 
00085  int median_for_hist_v1(const unsigned* hist, const int& low, const int& high, const unsigned& count);
00086  float  median_for_hist(const unsigned* hist, const int& low, const int& high, const unsigned& count);
00087 
00088 //--------------------
00089 // Code from ami/event/FrameCalib.cc
00090 // int median(ndarray<const uint32_t,2> d, unsigned& iLo, unsigned& iHi);
00091 
00092 //--------------------
00093 
00094 //--------------------
00095 // Philip Hart's code from psalg/src/common_mode.cc:
00096 //
00097 // averages all values in array "data" for length "length"
00098 // that are below "threshold".  If the magniture of the correction
00099 // is greater than "maxCorrection" leave "data" unchanged, otherwise
00100 // subtract the average in place.  
00101 // mask is either a null pointer (in which case nothing is masked)
00102 // or a list of values arranged like the data where non-zero means ignore
00103 
00104    template <typename T>
00105    void commonMode(T* data, const uint16_t* mask, const unsigned length, const T threshold, const T maxCorrection, T& cm) {
00106      // do dumbest thing possible to start - switch to median
00107      // do 2nd dumbest thing possible to start - switch to median
00108      cm = 0;
00109      T* tmp = data;
00110      double sum = 0;
00111      int nSummed = 0;
00112      for (unsigned col=0; col<length; col++) {
00113        T cval = *tmp++;
00114        T mval = (mask) ? *mask++ : 0;
00115        if (mval==0 && cval<threshold) {
00116          nSummed++;
00117          sum += cval;
00118        }
00119      }
00120      
00121      if (nSummed>0) {
00122        T mean = (T)(sum/nSummed);
00123        if (fabs(mean)<=maxCorrection) {
00124          cm = mean;
00125          tmp = data;
00126          for (unsigned col=0; col<length; col++) {
00127            *tmp++ -= cm;
00128          }
00129        }
00130      }
00131    }
00132 
00133 //--------------------
00134 //--------------------
00135 // Philip Hart's code from psalg/src/common_mode.cc:
00136 //
00137 // finds median of values in array "data" for length "length"
00138 // that are below "threshold".  If the magniture of the correction
00139 // is greater than "maxCorrection" leave "data" unchanged, otherwise
00140 // subtract the median in place.  
00141 // mask is either a null pointer (in which case nothing is masked)
00142 // or a list of values arranged like the data where non-zero means ignore
00143 
00144 template <typename T>
00145 void commonModeMedian(const T* data, const uint16_t* mask, const unsigned length, const T threshold, const T maxCorrection, T& cm) {
00146   cm = 0;
00147   const T* tmp = data;
00148 
00149   const uint32_t lMax = 32768;//2**14*2;  // here I may be assuming data in ADU
00150   const uint32_t lHalfMax = 16384;//2**14;
00151   const int      iMax = (int)lMax;
00152   const int      iHalfMax = (int)lHalfMax;
00153   unsigned hist[lMax];
00154   //memset(hist, 0, sizeof(unsigned)*lMax);
00155   std::fill_n(&hist[0], int(lMax), unsigned(0));
00156   int nSummed = 0;
00157 
00158   for (unsigned col=0; col<length; col++) {
00159     T cval = *tmp++;
00160     T mval = (mask) ? *mask++ : 0;
00161     if (mval==0 && cval<threshold) {
00162       nSummed++;
00163       //unsigned bin = (int)cval+lHalfMax;
00164       // unsigned long?  check range or raise?
00165       int bin = (int)cval+lHalfMax;
00166       if (bin<0) bin = 0;
00167       if (!(bin<iMax)) bin = lMax-1;
00168       hist[bin]++;
00169     }
00170   }
00171 
00172   if (nSummed==0) return;
00173 
00174   unsigned medianCount = (unsigned)ceil(nSummed/2.);
00175   unsigned histSum = 0;
00176   for (int bin=0; bin<iMax; bin++) {
00177     histSum += hist[bin];
00178     if (histSum>=medianCount) {
00179       T median = (int)bin - iHalfMax;
00180       if (fabs(median)<=maxCorrection) {
00181         cm = median;
00182       }
00183       return;
00184     }
00185   }
00186 }
00187 
00188 //--------------------
00189 // Apply "median" common mode correction.
00190 // Signature of this function has non-const data.
00191 template <typename T>
00192 void commonModeMedian(T* data, const uint16_t* mask, const unsigned length, const T threshold, const T maxCorrection, T& cm) {
00193   commonModeMedian((const T*)data, mask, length, threshold, maxCorrection, cm);
00194   if (cm != 0) {
00195     T* tmp = data;
00196     for (unsigned col=0; col<length; col++) {
00197       *tmp++ -= cm;
00198     }
00199   }
00200 }
00201 
00202 //--------------------
00203 //--------------------
00204 // This method was originally designed by Andy for CSPAD in pdscalibdata/src/CsPadCommonModeSubV1.cpp
00205 // - data type int16_t is changed to T
00206 // - subtract CM inside this module
00207 // - pedestal is not subtracted in this algorithm; assume that it is already subtracted
00208 
00209   /**
00210    *  Find common mode for an CsPad  section.
00211    *  
00212    *  Function will return UnknownCM value if the calculation 
00213    *  cannot be performed (or need not be performed).
00214    *  
00215    *  @param pars   array[3] of control parameters; mean_max, sigma_max, threshold on number of pixels/ADC count
00216    *  @param sdata  pixel data
00217    *  @param pixStatus  pixel status data, can be zero pointer
00218    *  @param ssize  size of all above arrays
00219    *  @param stride increment for pixel indices
00220    */ 
00221 
00222    //float cm_corr =  findCommonMode<T>(pars, sdata, pixStatus, ssize, nSect); 
00223 
00224 //--------------------
00225 // Modified Philip Hart's commonMode (mean) code (see below) for 2-d region in data. 
00226 
00227 template <typename T>
00228   void meanInRegion(  const double* pars
00229                     , ndarray<T,2>& data 
00230                     , ndarray<const uint16_t,2>& status
00231                     , const size_t& rowmin
00232                     , const size_t& colmin
00233                     , const size_t& nrows
00234                     , const size_t& ncols
00235                     , const size_t& srows = 1
00236                     , const size_t& scols = 1
00237                     , const unsigned& pbits=0
00238                     ) {
00239 
00240      T threshold = pars[1];
00241      T maxcorr   = pars[2];
00242 
00243      double sumv = 0;
00244      int    sum1 = 0;
00245      bool   check_status = (status.data()) ? true : false;
00246 
00247      for (size_t r=rowmin; r<rowmin+nrows; r+=srows) { 
00248        for (size_t c=colmin; c<colmin+ncols; c+=scols) {
00249          T v = data[r][c];
00250          T s = (check_status) ? status[r][c] : 0;
00251          if (s==0 && v<threshold) {
00252            sumv += v;
00253            sum1 ++;
00254          }
00255        }
00256      }
00257      
00258      if (sum1>0) {
00259        T mean = (T)(sumv/sum1);
00260 
00261        if (pbits) std::cout << "  mean:" << mean
00262                             << "  threshold:" << threshold
00263                             << '\n';
00264 
00265        if (fabs(mean)<=maxcorr) {
00266          for (size_t r=rowmin; r<rowmin+nrows; r+=srows) { 
00267            for (size_t c=colmin; c<colmin+ncols; c+=scols) {
00268              data[r][c] -= mean;
00269            }
00270          }
00271        }
00272      }
00273 }
00274 //--------------------
00275 // Median, similar to ami/event/FrameCalib::median, 
00276 // but finding median for entire good statistics w/o discarding edge bins
00277 
00278   template <typename T>
00279   void medianInRegion(const double* pars
00280                     , ndarray<T,2>& data 
00281                     , ndarray<const uint16_t,2>& status
00282                     , const size_t& rowmin
00283                     , const size_t& colmin
00284                     , const size_t& nrows
00285                     , const size_t& ncols
00286                     , const size_t& srows = 1
00287                     , const size_t& scols = 1
00288                     , const unsigned& pbits=0
00289                     ) {
00290 
00291       int hint_range = (int)pars[1];
00292       int maxcorr    = (int)pars[2];
00293 
00294       bool check_status = (status.data()) ? true : false;
00295 
00296       // declare array for histogram
00297       int half_range = max(int(hint_range), 10);
00298 
00299       int low  = -half_range;
00300       int high =  half_range;
00301       unsigned* hist  = 0;
00302       int       nbins = 0;
00303       int       bin   = 0;
00304       unsigned  iter  = 0;
00305       unsigned  count = 0;
00306 
00307       while(1) { // loop continues untill the range does not contain a half of statistics
00308 
00309           iter ++;
00310 
00311           nbins = high-low+1;
00312           if (nbins>10000) {
00313             if (pbits & 4) MsgLog("medianInRegion", warning, "Too many bins " << nbins 
00314                                   << ", common mode correction is not allied");
00315             return;
00316           }
00317 
00318           if (hist) delete[] hist;
00319           hist = new unsigned[nbins];
00320           std::fill_n(hist, nbins, 0);
00321           count = 0;
00322       
00323           // fill histogram
00324           for (size_t r=rowmin; r<rowmin+nrows; r+=srows) { 
00325             for (size_t c=colmin; c<colmin+ncols; c+=scols) {
00326             
00327               // ignore pixels that are too noisy; discard pixels with any status > 0
00328               if (check_status && status[r][c]) continue;
00329             
00330               bin = int(data[r][c]) - low;            
00331               if      (bin < 1)     hist[0]++;
00332               else if (bin < nbins) hist[bin]++;
00333               else                  hist[nbins-1]++;
00334               count++;
00335             }
00336           }
00337           
00338           if (pbits & 2) {
00339               MsgLog("medianInRegion", info, "Iter:" << iter 
00340                                    << "  histo nbins:" << nbins 
00341                                    << "  low:" << low 
00342                                    << "  high:" << high 
00343                                    << "  count:" << count);
00344               for (int b=0; b<nbins; ++b) std::cout << " " << b << ":" << hist[b]; 
00345               std::cout  << '\n';
00346           }
00347     
00348           // do not apply correction if the number of good pixels is small
00349           if (count < 10) {delete[] hist; return;}
00350 
00351           if (hist[0]>count/2) {
00352             if (maxcorr && low < -maxcorr) {delete[] hist; return;} // do not apply cm correction
00353             low  -= nbins/4;
00354           }
00355           else if (hist[nbins-1]>count/2) {
00356             if (maxcorr && high > maxcorr) {delete[] hist; return;} // do not apply cm correction
00357             high += nbins/4;
00358           }
00359           else
00360             break; 
00361       } // while(1)
00362 
00363       //--------------------
00364 
00365       T cm = (T)median_for_hist(hist, low, high, count);
00366 
00367       if (maxcorr && fabs(cm)>maxcorr) {delete[] hist; return;} // do not apply cm correction
00368 
00369       if (pbits & 1) MsgLog("medianInRegionV2", info, "cm correction = " << cm);
00370 
00371       // Apply common mode correction to data
00372       for (size_t r=rowmin; r<rowmin+nrows; r+=srows) { 
00373         for (size_t c=colmin; c<colmin+ncols; c+=scols) {
00374           data[r][c] -= cm;
00375         }
00376       }
00377 
00378       delete[] hist; 
00379   }
00380 
00381 //--------------------
00382 //--------------------
00383 // Median suggested by Silke on 2016/04/12 for Epix100a
00384 
00385   template <typename T>
00386   void medianInRegionV2(const double* pars
00387                     , ndarray<T,2>& data 
00388                     , ndarray<const uint16_t,2>& status
00389                     , const size_t& rowmin
00390                     , const size_t& colmin
00391                     , const size_t& nrows
00392                     , const size_t& ncols
00393                     , const size_t& srows = 1
00394                     , const size_t& scols = 1
00395                     , const unsigned& pbits=0
00396                     ) {
00397 
00398     //static unsigned nentry=0; nentry++;
00399     //if(nentry<2) cout << "medianInRegionV2\n";
00400 
00401       int hint_range = (int)pars[1];
00402       int maxcorr    = (int)pars[2];
00403 
00404       bool check_status = (status.data()) ? true : false;
00405 
00406       // declare array for histogram
00407       int half_range = max(int(hint_range), 10);
00408 
00409       int       low   = -half_range;
00410       int       high  =  half_range;
00411       int       bin   = 0;
00412       unsigned  count = 0;
00413       int       nbins = high-low+1;
00414       unsigned* hist  = new unsigned[nbins];
00415       std::fill_n(hist, nbins, 0);
00416       
00417       // fill histogram
00418       for (size_t r=rowmin; r<rowmin+nrows; r+=srows) { 
00419         for (size_t c=colmin; c<colmin+ncols; c+=scols) {
00420         
00421           // ignore pixels that are too noisy; discard pixels with any status > 0
00422           if (check_status && status[r][c]) continue;
00423         
00424           bin = floor(data[r][c]) - low;            
00425           if      (bin < 1)     hist[0]++;
00426           else if (bin < nbins) hist[bin]++;
00427           else                  hist[nbins-1]++;
00428           count++;
00429         }
00430       }
00431       
00432       if (pbits & 2) {
00433           MsgLog("medianInRegionV2", info,
00434                                   "  histo nbins:" << nbins 
00435                                << "  low:" << low 
00436                                << "  high:" << high 
00437                                << "  count:" << count);
00438           for (int b=0; b<nbins; ++b) std::cout << " " << b << ":" << hist[b]; 
00439           std::cout  << '\n';
00440       }
00441     
00442       // do not apply correction if
00443       if (count < 10            // the number of good pixels is small
00444       or  hist[0]>count/2        // more than half statistics in the edge bin
00445       or  hist[nbins-1]>count/2) {
00446           delete[] hist; return; 
00447       }
00448 
00449       T cm = (T)median_for_hist(hist, low, high, count);
00450 
00451       if (maxcorr && fabs(cm)>maxcorr) {delete[] hist; return;} // do not apply cm correction
00452 
00453       if (pbits & 1) MsgLog("medianInRegionV2", info, "cm correction = " << cm);
00454 
00455       // Apply common mode correction to data
00456       for (size_t r=rowmin; r<rowmin+nrows; r+=srows) { 
00457         for (size_t c=colmin; c<colmin+ncols; c+=scols) {
00458           data[r][c] -= cm;
00459         }
00460       }
00461 
00462       delete[] hist; 
00463   }
00464 
00465 //--------------------
00466 
00467 template <typename T>
00468 T median(std::vector<T> v)
00469 {
00470     int size = v.size();
00471     //int mid = (float(size)/2);
00472     int mid = size/2;
00473     sort(v.begin(), v.end());
00474     // cout << "size=" << size; for (int i=mid-5; i<mid+5; i++) cout << ' ' << v[i]; cout << '\n';
00475     return (size % 2 == 0) ? (v[mid] + v[mid-1]) / 2 : v[mid];
00476 }
00477 
00478 //--------------------
00479 //--------------------
00480 // Another median algorithm
00481 
00482   template <typename T>
00483   void medianInRegionV3(const double* pars
00484                     , ndarray<T,2>& data 
00485                     , ndarray<const uint16_t,2>& status
00486                     , const size_t& rowmin
00487                     , const size_t& colmin
00488                     , const size_t& nrows
00489                     , const size_t& ncols
00490                     , const size_t& srows = 1
00491                     , const size_t& scols = 1
00492                     , const unsigned& pbits=0
00493                     ) {
00494 
00495     //static unsigned nentry=0; nentry++;
00496     //if(nentry<2) cout << "medianInRegionV2\n";
00497 
00498       T half_range = (T)pars[1];
00499       T maxcorr    = (T)pars[2];
00500       T d = 0;
00501 
00502       bool check_status = (status.data()) ? true : false;
00503 
00504       std::vector<T> vec(nrows*ncols);
00505       vec.clear();
00506 
00507       // fill vector
00508       for (size_t r=rowmin; r<rowmin+nrows; r+=srows) { 
00509         for (size_t c=colmin; c<colmin+ncols; c+=scols) {
00510           if (check_status && status[r][c]) continue;
00511           d = data[r][c]; 
00512           if(d >  half_range) continue;
00513           if(d < -half_range) continue;   
00514           vec.push_back(d);
00515         }
00516       }
00517 
00518       if (vec.size() < 10) return;
00519 
00520       T cm = median<T>(vec);
00521 
00522       if (maxcorr && fabs(cm)>maxcorr) return; // do not apply cm correction
00523 
00524       if (pbits & 1) MsgLog("medianInRegionV3", info, "vec.size = " << vec.size() << "  cm correction = " << cm);
00525       //cout << "medianInRegionV3 vec.size = " << vec.size() << "  cm correction = " << cm << "\n";
00526 
00527       // Apply common mode correction to data
00528       for (size_t r=rowmin; r<rowmin+nrows; r+=srows) { 
00529         for (size_t c=colmin; c<colmin+ncols; c+=scols) {
00530           data[r][c] -= cm;
00531         }
00532       }
00533   }
00534 
00535 //--------------------
00536   /**
00537    *  Find common mode for CSPAD 2x1 section using unbond pixels.
00538    *
00539    *  @param pars   array[1] of control parameters; mean_max - maximal allowed correction
00540    *  @param sdata  pixel data
00541    *  @param ssize  size of data array (188*388)
00542    *  @param stride increment for pixel indices
00543    */ 
00544    //float cm_corr = applyCModeUnbond<T>(pars, sdata, ssize, stride); 
00545 
00546 template <typename T>
00547 float 
00548 applyCModeUnbond( const double* pars,
00549                   T* sdata,
00550                   unsigned ssize,
00551                   int stride = 1
00552                 )
00553 {
00554   int    npix = 0;
00555   double mean = 0;
00556   int    ind  = 0;
00557 
00558   //skip p=0 in the corner
00559   for (size_t r=10; r<ROWS2X1; r+=10) {      
00560     ind = (r*COLS2X1 + r)*stride;
00561     mean += sdata[ind] + sdata[ind+COLSHALF*stride];
00562     npix += 2; 
00563   }
00564 
00565   mean = (npix>0) ? mean/npix : 0;
00566 
00567   //std::cout << "XXX: applyCModeUnbond mean = " << mean << " evaluated for npix = " << npix << '\n';
00568 
00569   // limit common mode correction to some reasonable numbers
00570   if (abs(mean) > pars[0]) return float(UnknownCM);
00571 
00572   //--------------------
00573   // subtract CM 
00574   for (unsigned c=0, p=0; c<ssize; ++c, p += stride) {
00575         sdata[p] -= mean;
00576   }
00577   return (float)mean;
00578 }
00579 
00580 template <typename T>
00581 float 
00582 findCommonMode(const double* pars,
00583                T* sdata,
00584                const uint16_t *pixStatus, 
00585                unsigned ssize,
00586                int stride = 1
00587                )
00588 {
00589   // do we even need it
00590   //if (m_mode == None) return float(UnknownCM);
00591 
00592   // for now it does not make sense to calculate common mode
00593   // if pedestals are not known
00594   // if (not peddata) return float(UnknownCM);
00595   
00596   // declare array for histogram
00597   const int low = -1000;
00598   const int high = 2000;
00599   const unsigned hsize = high-low;
00600   int hist[hsize];
00601   std::fill_n(hist, hsize, 0);
00602   unsigned long count = 0;
00603 
00604   // fill histogram
00605   for (unsigned c = 0, p = 0; c != ssize; ++ c, p += stride) {
00606     // ignore channels that re too noisy
00607     //if (pixStatus and (pixStatus[p] & 1)) continue;
00608     if (pixStatus and pixStatus[p]) continue; // Discard  pixels with any status > 0
00609 
00610     // pixel value with pedestal subtracted, rounded to integer
00611     double dval = sdata[p]; // - peddata[p];
00612     int val = dval < 0 ? int(dval - 0.5) : int(dval + 0.5);
00613     
00614     // histogram bin
00615     unsigned bin = unsigned(val - low);
00616     
00617     // increment bin value if in range
00618     if (bin < hsize) {
00619       ++hist[bin] ;
00620       ++ count;
00621     }      
00622   }
00623   MsgLog("findCommonMode", debug, "histo filled count = " << count);
00624   
00625   // analyze histogram now, first find peak position
00626   // as the position of the lowest bin with highest count 
00627   // larger than 100 and which has a bin somewhere on 
00628   // right side with count dropping by half
00629   int peakPos = -1;
00630   int peakCount = -1;
00631   int hmRight = hsize;
00632   int thresh = int(pars[2]);
00633   if(thresh<=0) thresh=100;
00634   for (unsigned i = 0; i < hsize; ++ i ) {
00635     if (hist[i] > peakCount and hist[i] > thresh) {
00636       peakPos = i;
00637       peakCount = hist[i];
00638     } else if (peakCount > 0 and hist[i] <= peakCount/2) {
00639       hmRight = i;
00640       break;
00641     }
00642   }
00643 
00644   // did we find anything resembling
00645   if (peakPos < 0) {
00646     MsgLog("findCommonMode", debug, "peakPos = " << peakPos);
00647     if (pars[3] > 0.1) {
00648       // if not use unbounded cm
00649       double mean = applyCModeUnbond(pars, sdata, ssize, stride);
00650       return mean;
00651     }
00652     else return float(UnknownCM);
00653   }
00654 
00655   // find half maximum channel on left side
00656   int hmLeft = -1;
00657   for (int i = peakPos; hmLeft < 0 and i >= 0; -- i) {
00658     if(hist[i] <= peakCount/2) hmLeft = i;
00659   }
00660   MsgLog("findCommonMode", debug, "peakPos = " << peakPos << " peakCount = " << peakCount 
00661       << " hmLeft = " << hmLeft << " hmRight = " << hmRight);
00662   
00663   // full width at half maximum
00664   int fwhm = hmRight - hmLeft;
00665   double sigma = fwhm / 2.36;
00666 
00667   // calculate mean and sigma
00668   double mean = peakPos;
00669   for (int j = 0; j < 2; ++j) {
00670     int s0 = 0;
00671     double s1 = 0;
00672     double s2 = 0;
00673     int d = int(sigma*2+0.5);
00674     for (int i = std::max(0,peakPos-d); i < int(hsize) and i <= peakPos+d; ++ i) {
00675       s0 += hist[i];
00676       s1 += (i-mean)*hist[i];
00677       s2 += (i-mean)*(i-mean)*hist[i];
00678     }
00679     mean = mean + s1/s0;
00680     sigma = std::sqrt(s2/s0 - (s1/s0)*(s1/s0));
00681   }
00682   mean += low;
00683 
00684   MsgLog("findCommonMode", debug, "mean = " << mean << " sigma = " << sigma);
00685 
00686   if (abs(mean) > pars[0] or sigma > pars[1]) {
00687     if (pars[3] > 0.1) {
00688       // try using unbounded common mode if this one fails
00689       mean = applyCModeUnbond(pars, sdata, ssize, stride);
00690       return mean;
00691     }
00692     else return float(UnknownCM);
00693   }
00694   //--------------------
00695   // subtract CM 
00696   for (unsigned c = 0, p = 0; c < ssize; ++ c, p += stride) {
00697         sdata[p] -= mean;
00698   }
00699 
00700   return mean;
00701 }
00702 //--------------------
00703 
00704 
00705 //--------------------
00706 // Optimized common mode correction algorithm for Epix100
00707 //
00708 // Optimizetion
00709 // ------------
00710 // 1. remove redundant loops comparing to medianInRegionV3
00711 // 2. work with float values in stead of double
00712 // 3. do not use vector-s
00713 
00714   template <typename T>
00715   void medianEpix100V1(const double* pars
00716                       ,ndarray<T,2>& data 
00717                       ,ndarray<const uint16_t,2>& status
00718                       ,const unsigned& pbits=0
00719                       ) {
00720 
00721     const unsigned shasd[2] = {704, 768};
00722     //const unsigned shtrd[2] = {768, 704};
00723 
00724     static unsigned nentry=0; nentry++;
00725     if(nentry==1) {
00726       //cout << "medianEpix100V1: cmpars = "; for(int i=0; i<3; i++) cout << " " << pars[i]; cout << '\n';
00727       //cout << "medianEpix100V1: sizeof(float)=" << sizeof(float) << '\n'; // the answer is 4 byte
00728       if (pbits & 1) MsgLog("medianEpix100V1", info, "cmpars = " << pars[0] << " " << pars[1] << " " << pars[2]);
00729 
00730       //SingleStore::instance()->print()
00731     }
00732 
00733     ndarray<work_t,2>& m_wasd = SingleStore::instance()->m_wasd;
00734     ndarray<work_t,2>& m_wtrd = SingleStore::instance()->m_wtrd;
00735     ndarray<work_t,2>& m_ctrd = SingleStore::instance()->m_ctrd;
00736 
00737     const work_t BADDATA = -100000.;
00738 
00739     //size_t nregs  = 16;       
00740     size_t nrows  = shasd[0]; // 704
00741     size_t ncols  = shasd[1]; // 768
00742     T half_range  = (T)pars[1];
00743     T maxcorr     = (work_t)pars[2];
00744 
00745     bool check_status = (status.data()) ? true : false;
00746 
00747     typename ndarray<T, 2>::iterator itd;
00748     typename ndarray<const uint16_t, 2>::iterator its=status.begin();
00749     typename ndarray<work_t, 2>::iterator itw=m_wasd.begin();
00750 
00751     // --------------------------------
00752     // Correction of 96 pixels in rows
00753     // --------------------------------
00754 
00755     // conditional copy of data to work array in right order
00756     for(itd=data.begin(); itd!=data.end(); itd++, its++, itw++) {
00757       bool bad_pixel = (check_status && *its) or (*itd>half_range) or (*itd<-half_range);
00758       *itw = (bad_pixel) ? BADDATA : (work_t)(*itd);
00759     }
00760 
00761     // loop over 1-d row parts in 2-d m_wasd array
00762     size_t grlen = 96; // ncols/8
00763     itd=data.begin();
00764     for(itw=m_wasd.begin(); itw!=m_wasd.end(); itw+=grlen, itd+=grlen) {
00765 
00766       // Edges of the row
00767       work_t* pbeg = itw;
00768       work_t* pend = itw+grlen; // assuming as usually [pbe,pend)
00769 
00770       // Sort elements
00771       std::sort(pbeg,pend);
00772       //cout << "\nXXX sorted:"; for(work_t* p=pbeg; p<pend; p++) cout << " " << *p; cout << '\n'; 
00773 
00774       // Discard bad pixels 
00775       for(; pbeg!=pend; pbeg++)
00776         if(*pbeg!=BADDATA) break;
00777       //cout << "\nXXX clean sorted:"; for(work_t* p=pbeg; p<pend; p++) cout << " " << *p; cout << '\n'; 
00778 
00779       int npix_good = pend-pbeg;
00780       if(npix_good<10) continue; // do not apply correction for small number of good pixels
00781       work_t cm = *(pbeg + npix_good/2);
00782       //cout << "\nXXX npix_good=" << npix_good << "  cm=" << cm << '\n'; 
00783 
00784       if(maxcorr && fabs(cm)>maxcorr) continue;  // do not apply large correction
00785       
00786       // apply correction to data part of the row
00787       for(T* p=itd; p!=itd+grlen; p++) *p -= cm;
00788     }
00789 
00790     // --------------------------------
00791     // Correction of 352 pixels in cols
00792     // --------------------------------
00793 
00794     // data has changed, so need to repeat conditional copy array again
00795     its=status.begin();
00796     itw=m_wasd.begin();
00797     for(itd=data.begin(); itd!=data.end(); itd++, its++, itw++) {
00798       bool bad_pixel = (check_status && *its) or (*itd>half_range) or (*itd<-half_range);
00799       *itw = (bad_pixel) ? BADDATA : (work_t)(*itd);
00800     }
00801 
00802     // Fill in transposed array
00803     for(size_t r=0; r<nrows; r++)
00804       for(size_t c=0; c<ncols; c++) {
00805         m_wtrd[c][r] = m_wasd[r][c];
00806         m_ctrd[c][r] = data[r][c];
00807       }
00808 
00809     // loop over 1-d row parts in 2-d m_wtrd array
00810     grlen = 352; // nrows/2
00811     typename ndarray<work_t, 2>::iterator itc=m_ctrd.begin();
00812     typename ndarray<work_t, 2>::iterator itr=m_wtrd.begin();
00813     for(itr=m_wtrd.begin(); itr!=m_wtrd.end(); itr+=grlen, itc+=grlen) {
00814 
00815       // Edges of the row
00816       work_t* pbeg = itr;
00817       work_t* pend = itr+grlen; // assuming as usually [pbe,pend)
00818 
00819       // Sort elements
00820       std::sort(pbeg,pend);
00821       //cout << "\nXXX sorted:"; for(work_t* p=pbeg; p<pend; p++) cout << " " << *p; cout << '\n'; 
00822 
00823       // Discard bad pixels 
00824       for(; pbeg!=pend; pbeg++)
00825         if(*pbeg!=BADDATA) break;
00826       //cout << "\nXXX clean sorted:"; for(work_t* p=pbeg; p<pend; p++) cout << " " << *p; cout << '\n'; 
00827 
00828       int npix_good = pend-pbeg;
00829       if(npix_good<10) continue; // do not apply correction for small number of good pixels
00830       work_t cm = *(pbeg + npix_good/2);
00831       //cout << "\nXXX npix_good=" << npix_good << "  cm=" << cm << '\n'; 
00832 
00833       if(maxcorr && fabs(cm)>maxcorr) continue;  // do not apply large correction
00834       
00835       // apply correction to transposed data part of the row
00836       for(work_t* p=itc; p!=itc+grlen; p++) *p -= cm;
00837     }
00838 
00839     // copy transposed corrected array to data
00840     for(size_t r=0; r<nrows; r++)
00841       for(size_t c=0; c<ncols; c++)
00842         data[r][c] = (T)m_ctrd[c][r];
00843   }
00844 
00845 //--------------------
00846 
00847 } // namespace ImgAlgos
00848 
00849 #endif // IMGALGOS_COMMONMODE_H

Generated on 19 Dec 2016 for PSDMSoftware by  doxygen 1.4.7