00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #ifndef FITTING_H
00019 #define FITTING_H
00020
00021 #include <odindata/data.h>
00022 #include <odindata/linalg.h>
00023 #include <odindata/utils.h>
00024
00025
00034 struct fitpar {
00035
00036 fitpar() : val(0.0), err(0.0) {}
00037
00041 float val;
00042
00046 float err;
00047 };
00048
00049
00051
00064 class ModelFunction {
00065
00066 public:
00067
00071 virtual float evaluate_f(float x) const = 0;
00072
00076 virtual fvector evaluate_df(float x) const = 0;
00077
00081 virtual unsigned int numof_fitpars() const = 0;
00082
00086 virtual fitpar& get_fitpar(unsigned int i) = 0;
00087
00088
00101 bool fit(const Array<float,1>& yvals,
00102 const Array<float,1>& ysigma=defaultArray,
00103 const Array<float,1>& xvals=defaultArray,
00104 unsigned int max_iterations=500, double tolerance=1.0e-4);
00105
00109 Array<float,1> get_function(const Array<float,1>& xvals) const;
00110
00111
00112
00113 static const Array<float,1> defaultArray;
00114
00115 protected:
00116 ModelFunction() {}
00117 virtual ~ModelFunction() {}
00118
00119 fitpar dummy_fitpar;
00120
00121 };
00122
00124
00125 class ModelData;
00126 class GslData4Fit;
00127
00131 class FunctionFit {
00132
00133 public:
00134
00139 FunctionFit(ModelFunction& model_func, unsigned int nvals, unsigned int max_iterations=500, double tolerance=1.0e-4);
00140
00144 ~FunctionFit();
00145
00154 bool fit(const Array<float,1>& yvals,
00155 const Array<float,1>& ysigma=defaultArray,
00156 const Array<float,1>& xvals=defaultArray);
00157
00158
00159
00160 static const Array<float,1> defaultArray;
00161
00162 private:
00163
00164 void print_state (size_t iter);
00165
00166 ModelFunction& func;
00167 unsigned int max_it;
00168 double tol;
00169
00170 GslData4Fit* gsldata;
00171 ModelData* data4fit;
00172 };
00173
00174
00175
00177
00178
00185 struct ExponentialFunction : public ModelFunction {
00186
00187 fitpar A;
00188 fitpar lambda;
00189
00190
00191 float evaluate_f(float x) const;
00192 fvector evaluate_df(float x) const;
00193 unsigned int numof_fitpars() const;
00194 fitpar& get_fitpar(unsigned int i);
00195 };
00196
00197
00199
00206 struct ExponentialFunctionWithOffset : public ModelFunction {
00207
00208 fitpar A;
00209 fitpar lambda;
00210 fitpar C;
00211
00212
00213 float evaluate_f(float x) const;
00214 fvector evaluate_df(float x) const;
00215 unsigned int numof_fitpars() const;
00216 fitpar& get_fitpar(unsigned int i);
00217 };
00218
00220
00221
00228 struct GaussianFunction : public ModelFunction {
00229
00230 fitpar A;
00231 fitpar x0;
00232 fitpar fwhm;
00233
00234
00235 float evaluate_f(float x) const;
00236 fvector evaluate_df(float x) const;
00237 unsigned int numof_fitpars() const;
00238 fitpar& get_fitpar(unsigned int i);
00239 };
00240
00241
00243
00244
00251 struct SinusFunction : public ModelFunction {
00252
00253 fitpar A;
00254 fitpar m;
00255 fitpar c;
00256
00257
00258 float evaluate_f(float x) const;
00259 fvector evaluate_df(float x) const;
00260 unsigned int numof_fitpars() const;
00261 fitpar& get_fitpar(unsigned int i);
00262 };
00263
00265
00274 template <int N_rank>
00275 struct PolynomialFunction {
00276
00277 fitpar a[N_rank+1];
00278
00289 bool fit(const Array<float,1>& yvals,
00290 const Array<float,1>& ysigma,
00291 const Array<float,1>& xvals);
00292
00293
00294 bool fit(const Array<float,1>& yvals,
00295 const Array<float,1>& ysigma){
00296 firstIndex fi;
00297 Array<float,1> xvals(yvals.size());
00298 xvals=fi;
00299 return fit(yvals,ysigma,xvals);
00300 };
00301
00302 bool fit(const Array<float,1>& yvals){
00303 Array<float,1> ysigma(yvals.size());
00304 ysigma=1.;
00305 return fit(yvals,ysigma);
00306 };
00307
00312 Array<float,1> get_function(const Array<float,1>& xvals) const;
00313
00314 };
00315
00316
00317 template <int N_rank>
00318 bool PolynomialFunction<N_rank>::fit(const Array<float,1>& yvals, const Array<float,1>& ysigma, const Array<float,1>& xvals) {
00319
00320 int npol=N_rank+1;
00321 for(int i=0; i<npol; i++) a[i]=fitpar();
00322
00323 int npts=yvals.size();
00324
00325 Array<float,1> sigma(npts);
00326 if(ysigma.size()==npts) sigma=ysigma;
00327 else sigma=1.0;
00328
00329 Array<float,1> x(npts);
00330 if(xvals.size()==npts) x=xvals;
00331 else for(int ipt=0; ipt<npts; ipt++) x(ipt)=ipt;
00332
00333
00334 Array<float,2> A(npts,npol);
00335 Array<float,1> b(npts);
00336
00337
00338 for(int ipt=0; ipt<npts; ipt++) {
00339 float weight=secureInv( sigma(ipt));
00340
00341 b(ipt)=weight*yvals(ipt);
00342
00343 for(int ipol=0; ipol<npol; ipol++) {
00344 A(ipt,ipol)=weight*pow(x(ipt),ipol);
00345 }
00346 }
00347
00348 Array<float,1> coeff(solve_linear(A,b));
00349
00350 for(int ipol=0; ipol<npol; ipol++) a[ipol].val=coeff(ipol);
00351
00352 return true;
00353 }
00354
00355
00356 template <int N_rank>
00357 Array<float,1> PolynomialFunction<N_rank>::get_function(const Array<float,1>& xvals) const {
00358 int npts=xvals.size();
00359 Array<float,1> result(npts); result=0.0;
00360
00361 for(int ipt=0; ipt<npts; ipt++) {
00362 for(int ipol=0; ipol<(N_rank+1); ipol++) {
00363 result(ipt)+=a[ipol].val*pow(xvals(ipt),ipol);
00364 }
00365 }
00366
00367 return result;
00368 }
00369
00370
00372
00373
00382 struct LinearFunction {
00383
00384 fitpar m;
00385 fitpar c;
00386
00397 bool fit(const Array<float,1>& yvals,
00398 const Array<float,1>& ysigma=defaultArray,
00399 const Array<float,1>& xvals=defaultArray);
00400
00405 Array<float,1> get_function(const Array<float,1>& xvals) const;
00406
00407
00408
00409 static const Array<float,1> defaultArray;
00410 };
00411
00412
00413
00415
00416
00430 template <int N_rank>
00431 Array<float,N_rank> polyniomial_fit(const Array<float,N_rank>& value_map, const Array<float,N_rank>& reliability_map,
00432 unsigned int polynom_order, float kernel_size, bool only_zero_reliability=false) {
00433 Log<OdinData> odinlog("","polyniomial_fit");
00434
00435 Data<float,N_rank> result(value_map.shape());
00436 result=0.0;
00437
00438 if(!same_shape(value_map,reliability_map)) {
00439 ODINLOG(odinlog,errorLog) << "size mismatch (value_map.shape()=" << value_map.shape() << ") != (reliability_map.shape()=" << reliability_map.shape() << ")" << STD_endl;
00440 return result;
00441 }
00442
00443 if(min(reliability_map)<0.0) {
00444 ODINLOG(odinlog,errorLog) << "reliability_map must be non-negative" << STD_endl;
00445 return result;
00446 }
00447
00448 int minsize=max(value_map.shape());
00449 for(int idim=0; idim<N_rank; idim++) {
00450 int dimsize=value_map.shape()(idim);
00451 if( (dimsize>1) && (dimsize<minsize) ) minsize=dimsize;
00452 }
00453 if(minsize<=0) {
00454 return result;
00455 }
00456
00457 if((minsize-1)<int(polynom_order)) {
00458 polynom_order=minsize-1;
00459 ODINLOG(odinlog,warningLog) << "array size too small, restricting polynom_order to " << polynom_order << STD_endl;
00460 }
00461
00462 TinyVector<int,N_rank> valshape(value_map.shape());
00463 int nvals=value_map.numElements();
00464
00465 TinyVector<int,N_rank> polsize; polsize=polynom_order+1;
00466 Data<int,N_rank> polarr(polsize);
00467 int npol=polarr.numElements();
00468
00469 if(pow(kernel_size,float(N_rank))<float(npol)) {
00470 kernel_size=pow(double(npol),double(1.0/float(N_rank)));
00471 ODINLOG(odinlog,warningLog) << "kernel_size too small for polynome, increasing to " << kernel_size << STD_endl;
00472 }
00473
00474
00475
00476 int neighb_pixel=int(kernel_size);
00477 if(neighb_pixel<=0) neighb_pixel=1;
00478 TinyVector<int,N_rank> neighbsize; neighbsize=2*neighb_pixel+1;
00479 TinyVector<int,N_rank> neighboffset; neighboffset=-neighb_pixel;
00480 Data<int,N_rank> neighbarr(neighbsize);
00481 int nneighb=neighbarr.numElements();
00482
00483 ODINLOG(odinlog,normalDebug) << "nvals/npol/nneighb=" << nvals << "/" << npol << "/" << nneighb << STD_endl;
00484
00485 if(npol>nneighb) {
00486 ODINLOG(odinlog,warningLog) << "polynome order (" << npol << ") larger than number of neighbours (" << nneighb << ")" << STD_endl;
00487 }
00488
00489
00490 Array<float,2> A(npol,npol);
00491 Array<float,1> c(npol);
00492 Array<float,1> b(npol);
00493
00494 TinyVector<int,N_rank> valindex;
00495 TinyVector<int,N_rank> neighbindex;
00496 TinyVector<int,N_rank> currindex;
00497 TinyVector<int,N_rank> diffindex;
00498 TinyVector<int,N_rank> polindex;
00499 TinyVector<int,N_rank> polindex_sum;
00500
00501 float epsilon=0.01;
00502 float relevant_radius=0.5*kernel_size*sqrt(double(N_rank))+epsilon;
00503
00504
00505 for(int ival=0; ival<nvals; ival++) {
00506 valindex=result.create_index(ival);
00507
00508 if( (!only_zero_reliability) || (reliability_map(valindex)<=0.0) ) {
00509
00510 A=0.0;
00511 b=0.0;
00512
00513 int n_relevant_neighb_pixel=0;
00514
00515
00516
00517 for(int ineighb=0; ineighb<nneighb; ineighb++) {
00518 neighbindex=neighbarr.create_index(ineighb);
00519 currindex=valindex+neighboffset+neighbindex;
00520
00521 bool valid_pixel=true;
00522
00523
00524 for(int irank=0; irank<N_rank; irank++) {
00525 if(currindex(irank)<0 || currindex(irank)>=valshape(irank)) valid_pixel=false;
00526 }
00527
00528
00529 float reliability=0.0;
00530 if(valid_pixel) reliability=reliability_map(currindex);
00531 if(reliability<=0.0) valid_pixel=false;
00532
00533
00534 if(valid_pixel) {
00535
00536 diffindex=currindex-valindex;
00537
00538 float radiussqr=sum(diffindex*diffindex);
00539 float weight=reliability*exp(-2.0*radiussqr/(kernel_size*kernel_size));
00540
00541 if(weight>0.0) {
00542 if(sqrt(radiussqr)<=relevant_radius) n_relevant_neighb_pixel++;
00543
00544
00545 for(int ipol=0; ipol<npol; ipol++) {
00546 polindex=polarr.create_index(ipol);
00547 float polproduct=1.0;
00548 for(int irank=0; irank<N_rank; irank++) polproduct*=pow(float(diffindex(irank)),float(polindex(irank)));
00549 b(ipol)+=weight*value_map(currindex)*polproduct;
00550 }
00551
00552
00553 for(int ipol=0; ipol<npol; ipol++) {
00554 for(int ipol_prime=0; ipol_prime<npol; ipol_prime++) {
00555 polindex_sum=polarr.create_index(ipol)+polarr.create_index(ipol_prime);
00556 float polproduct=1.0;
00557 for(int irank=0; irank<N_rank; irank++) polproduct*=pow(float(diffindex(irank)),float(polindex_sum(irank)));
00558 A(ipol,ipol_prime)+=weight*polproduct;
00559 }
00560 }
00561
00562 }
00563
00564
00565 }
00566 }
00567
00568 if(n_relevant_neighb_pixel>=npol) {
00569 c=solve_linear(A,b);
00570 result(valindex)=c(0);
00571 }
00572
00573 } else result(valindex)=value_map(valindex);
00574
00575 }
00576
00577 return result;
00578 }
00579
00580
00585 #endif
00586