00001 #ifndef IMGALGOS_COMMONMODE_H
00002 #define IMGALGOS_COMMONMODE_H
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include <string>
00018 #include <vector>
00019 #include <fstream>
00020 #include <iomanip>
00021 #include <sstream>
00022 #include <stdint.h>
00023 #include <iostream>
00024 #include <cmath>
00025 #include <algorithm>
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
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
00058
00059
00060
00061 ndarray<work_t,2> m_wasd;
00062 ndarray<work_t,2> m_wtrd;
00063 ndarray<work_t,2> m_ctrd;
00064
00065 private:
00066
00067 SingleStore() ;
00068 virtual ~SingleStore(){};
00069
00070 static SingleStore* m_pInstance;
00071
00072
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
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
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
00107
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
00136
00137
00138
00139
00140
00141
00142
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;
00150 const uint32_t lHalfMax = 16384;
00151 const int iMax = (int)lMax;
00152 const int iHalfMax = (int)lHalfMax;
00153 unsigned hist[lMax];
00154
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
00164
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
00190
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
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
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
00276
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
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) {
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
00324 for (size_t r=rowmin; r<rowmin+nrows; r+=srows) {
00325 for (size_t c=colmin; c<colmin+ncols; c+=scols) {
00326
00327
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
00349 if (count < 10) {delete[] hist; return;}
00350
00351 if (hist[0]>count/2) {
00352 if (maxcorr && low < -maxcorr) {delete[] hist; return;}
00353 low -= nbins/4;
00354 }
00355 else if (hist[nbins-1]>count/2) {
00356 if (maxcorr && high > maxcorr) {delete[] hist; return;}
00357 high += nbins/4;
00358 }
00359 else
00360 break;
00361 }
00362
00363
00364
00365 T cm = (T)median_for_hist(hist, low, high, count);
00366
00367 if (maxcorr && fabs(cm)>maxcorr) {delete[] hist; return;}
00368
00369 if (pbits & 1) MsgLog("medianInRegionV2", info, "cm correction = " << cm);
00370
00371
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
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
00399
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
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
00418 for (size_t r=rowmin; r<rowmin+nrows; r+=srows) {
00419 for (size_t c=colmin; c<colmin+ncols; c+=scols) {
00420
00421
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
00443 if (count < 10
00444 or hist[0]>count/2
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;}
00452
00453 if (pbits & 1) MsgLog("medianInRegionV2", info, "cm correction = " << cm);
00454
00455
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
00472 int mid = size/2;
00473 sort(v.begin(), v.end());
00474
00475 return (size % 2 == 0) ? (v[mid] + v[mid-1]) / 2 : v[mid];
00476 }
00477
00478
00479
00480
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
00496
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
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;
00523
00524 if (pbits & 1) MsgLog("medianInRegionV3", info, "vec.size = " << vec.size() << " cm correction = " << cm);
00525
00526
00527
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
00538
00539
00540
00541
00542
00543
00544
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
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
00568
00569
00570 if (abs(mean) > pars[0]) return float(UnknownCM);
00571
00572
00573
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
00590
00591
00592
00593
00594
00595
00596
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
00605 for (unsigned c = 0, p = 0; c != ssize; ++ c, p += stride) {
00606
00607
00608 if (pixStatus and pixStatus[p]) continue;
00609
00610
00611 double dval = sdata[p];
00612 int val = dval < 0 ? int(dval - 0.5) : int(dval + 0.5);
00613
00614
00615 unsigned bin = unsigned(val - low);
00616
00617
00618 if (bin < hsize) {
00619 ++hist[bin] ;
00620 ++ count;
00621 }
00622 }
00623 MsgLog("findCommonMode", debug, "histo filled count = " << count);
00624
00625
00626
00627
00628
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
00645 if (peakPos < 0) {
00646 MsgLog("findCommonMode", debug, "peakPos = " << peakPos);
00647 if (pars[3] > 0.1) {
00648
00649 double mean = applyCModeUnbond(pars, sdata, ssize, stride);
00650 return mean;
00651 }
00652 else return float(UnknownCM);
00653 }
00654
00655
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
00664 int fwhm = hmRight - hmLeft;
00665 double sigma = fwhm / 2.36;
00666
00667
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
00689 mean = applyCModeUnbond(pars, sdata, ssize, stride);
00690 return mean;
00691 }
00692 else return float(UnknownCM);
00693 }
00694
00695
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
00707
00708
00709
00710
00711
00712
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
00723
00724 static unsigned nentry=0; nentry++;
00725 if(nentry==1) {
00726
00727
00728 if (pbits & 1) MsgLog("medianEpix100V1", info, "cmpars = " << pars[0] << " " << pars[1] << " " << pars[2]);
00729
00730
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
00740 size_t nrows = shasd[0];
00741 size_t ncols = shasd[1];
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
00753
00754
00755
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
00762 size_t grlen = 96;
00763 itd=data.begin();
00764 for(itw=m_wasd.begin(); itw!=m_wasd.end(); itw+=grlen, itd+=grlen) {
00765
00766
00767 work_t* pbeg = itw;
00768 work_t* pend = itw+grlen;
00769
00770
00771 std::sort(pbeg,pend);
00772
00773
00774
00775 for(; pbeg!=pend; pbeg++)
00776 if(*pbeg!=BADDATA) break;
00777
00778
00779 int npix_good = pend-pbeg;
00780 if(npix_good<10) continue;
00781 work_t cm = *(pbeg + npix_good/2);
00782
00783
00784 if(maxcorr && fabs(cm)>maxcorr) continue;
00785
00786
00787 for(T* p=itd; p!=itd+grlen; p++) *p -= cm;
00788 }
00789
00790
00791
00792
00793
00794
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
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
00810 grlen = 352;
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
00816 work_t* pbeg = itr;
00817 work_t* pend = itr+grlen;
00818
00819
00820 std::sort(pbeg,pend);
00821
00822
00823
00824 for(; pbeg!=pend; pbeg++)
00825 if(*pbeg!=BADDATA) break;
00826
00827
00828 int npix_good = pend-pbeg;
00829 if(npix_good<10) continue;
00830 work_t cm = *(pbeg + npix_good/2);
00831
00832
00833 if(maxcorr && fabs(cm)>maxcorr) continue;
00834
00835
00836 for(work_t* p=itc; p!=itc+grlen; p++) *p -= cm;
00837 }
00838
00839
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 }
00848
00849 #endif // IMGALGOS_COMMONMODE_H