00001 #include "../interface/th1fmorph.h"
00002 #include "TROOT.h"
00003 #include "TAxis.h"
00004 #include "TArrayD.h"
00005
00006 #include <iostream>
00007 #include <cmath>
00008 #include <set>
00009
00010 using namespace std;
00011
00012 template<typename TH1_t, typename Value_t>
00013 TH1_t *th1fmorph_(const char *chname,
00014 const char *chtitle,
00015 TH1_t *hist1,TH1_t *hist2,
00016 Double_t par1,Double_t par2,Double_t parinterp,
00017 Double_t morphedhistnorm,
00018 Int_t idebug)
00019 {
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079 if(!hist1) {
00080 cout << "ERROR! th1morph says first input histogram doesn't exist." << endl;
00081 return(0);
00082 }
00083 if(!hist2) {
00084 cout << "ERROR! th1morph says second input histogram doesn't exist." << endl;
00085 return(0);
00086 }
00087
00088
00089
00090
00091 TAxis* axis1 = hist1->GetXaxis();
00092 Int_t nb1 = axis1->GetNbins();
00093 TAxis* axis2 = hist2->GetXaxis();
00094 Int_t nb2 = axis2->GetNbins();
00095
00096 std::set<Double_t> bedgesn_tmp;
00097 for(Int_t i = 1; i <= nb1; ++i){
00098 bedgesn_tmp.insert(axis1->GetBinLowEdge(i));
00099 bedgesn_tmp.insert(axis1->GetBinUpEdge(i));
00100 }
00101 for(Int_t i = 1; i <= nb2; ++i){
00102 bedgesn_tmp.insert(axis2->GetBinLowEdge(i));
00103 bedgesn_tmp.insert(axis2->GetBinUpEdge(i));
00104 }
00105 Int_t nbn = bedgesn_tmp.size() - 1;
00106 TArrayD bedgesn(nbn+1);
00107 Int_t idx = 0;
00108 for (std::set<Double_t>::const_iterator bedge = bedgesn_tmp.begin();
00109 bedge != bedgesn_tmp.end(); ++bedge){
00110 bedgesn[idx]=(*bedge);
00111 ++idx;
00112 }
00113 Double_t xminn = bedgesn[0];
00114 Double_t xmaxn = bedgesn[nbn];
00115
00116
00117
00118
00119
00120
00121
00122
00123 Double_t wt1,wt2;
00124 if (par2 != par1) {
00125 wt1 = 1. - (parinterp-par1)/(par2-par1);
00126 wt2 = 1. + (parinterp-par2)/(par2-par1);
00127 }
00128 else {
00129 wt1 = 0.5;
00130 wt2 = 0.5;
00131 }
00132
00133
00134
00135 if (wt1 < 0 || wt1 > 1. || wt2 < 0. || wt2 > 1. || fabs(1-(wt1+wt2))
00136 > 1.0e-4) {
00137 cout << "Warning! th1fmorph: This is an extrapolation!! Weights are "
00138 << wt1 << " and " << wt2 << " (sum=" << wt1+wt2 << ")" << endl;
00139 }
00140 if (idebug >= 1) cout << "th1morph - Weights: " << wt1 << " " << wt2 << endl;
00141
00142 if (idebug >= 1) cout << "New hist: " << nbn << " " << xminn << " "
00143 << xmaxn << endl;
00144
00145
00146
00147
00148 if (hist1->GetSum() <= 0 || hist2->GetSum() <=0 ) {
00149 cout << "Warning! th1morph detects an empty input histogram. Empty interpolated histogram returned: "
00150 <<endl << " " << chname << " - " << chtitle << endl;
00151 TH1_t *morphedhist = (TH1_t *)gROOT->FindObject(chname);
00152 if (morphedhist) delete morphedhist;
00153 morphedhist = new TH1_t(chname,chtitle,nbn,xminn,xmaxn);
00154 return(morphedhist);
00155 }
00156 if (idebug >= 1) cout << "Input histogram content sums: "
00157 << hist1->GetSum() << " " << hist2->GetSum() << endl;
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170 Value_t *dist1=hist1->GetArray();
00171 Value_t *dist2=hist2->GetArray();
00172 Double_t *sigdis1 = new Double_t[1+nb1];
00173 Double_t *sigdis2 = new Double_t[1+nb2];
00174 Double_t *sigdisn = new Double_t[2+nb1+nb2];
00175 Double_t *xdisn = new Double_t[2+nb1+nb2];
00176 Double_t *sigdisf = new Double_t[nbn+1];
00177
00178 for(Int_t i=0;i<2+nb1+nb2;i++) xdisn[i] = 0;
00179 sigdis1[0] = 0; sigdis2[0] = 0;
00180
00181 for(Int_t i=1;i<nb1+1;i++) {
00182 sigdis1[i] = dist1[i];
00183 }
00184 for(Int_t i=1;i<nb2+1;i++) {
00185 sigdis2[i] = dist2[i];
00186 }
00187
00188 if (idebug >= 3) {
00189 for(Int_t i=0;i<nb1+1;i++) {
00190 cout << i << " dist1" << dist1[i] << endl;
00191 }
00192 for(Int_t i=0;i<nb2+1;i++) {
00193 cout << i << " dist2" << dist2[i] << endl;
00194 }
00195 }
00196
00197
00198
00199
00200 Double_t total = 0;
00201 for(Int_t i=0;i<nb1+1;i++) {
00202 total += sigdis1[i];
00203 }
00204 if (idebug >=1) cout << "Total histogram 1: " << total << endl;
00205 for(Int_t i=1;i<nb1+1;i++) {
00206 sigdis1[i] = sigdis1[i]/total + sigdis1[i-1];
00207 }
00208
00209 total = 0.;
00210 for(Int_t i=0;i<nb2+1;i++) {
00211 total += sigdis2[i];
00212 }
00213 if (idebug >=1) cout << "Total histogram 22: " << total << endl;
00214 for(Int_t i=1;i<nb2+1;i++) {
00215 sigdis2[i] = sigdis2[i]/total + sigdis2[i-1];
00216 }
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226 Int_t ix1l = nb1;
00227 Int_t ix2l = nb2;
00228 while(sigdis1[ix1l-1] >= sigdis1[ix1l]) {
00229 ix1l = ix1l - 1;
00230 }
00231 while(sigdis2[ix2l-1] >= sigdis2[ix2l]) {
00232 ix2l = ix2l - 1;
00233 }
00234
00235
00236
00237
00238
00239 Int_t ix1 = -1;
00240 do {
00241 ix1 = ix1 + 1;
00242 } while(sigdis1[ix1+1] <= sigdis1[0]);
00243
00244 Int_t ix2 = -1;
00245 do {
00246 ix2 = ix2 + 1;
00247 } while(sigdis2[ix2+1] <= sigdis2[0]);
00248
00249 if (idebug >= 1) {
00250 cout << "First and last edge of hist1: " << ix1 << " " << ix1l << endl;
00251 cout << " " << sigdis1[ix1] << " " << sigdis1[ix1+1] << endl;
00252 cout << "First and last edge of hist2: " << ix2 << " " << ix2l << endl;
00253 cout << " " << sigdis2[ix2] << " " << sigdis2[ix2+1] << endl;
00254 }
00255
00256
00257
00258 Int_t nx3 = 0;
00259 Double_t x1,x2,x;
00260 x1 = axis1->GetBinLowEdge(ix1+1);
00261 x2 = axis2->GetBinLowEdge(ix2+1);
00262 x = wt1*x1 + wt2*x2;
00263 xdisn[nx3] = x;
00264 sigdisn[nx3] = 0;
00265 if(idebug >= 1) {
00266 cout << "First interpolated point: " << xdisn[nx3] << " "
00267 << sigdisn[nx3] << endl;
00268 cout << " " << x1 << " <= " << x << " <= "
00269 << x2 << endl;
00270 }
00271
00272
00273
00274
00275
00276 if (idebug >= 1) {
00277 cout << "----BEFORE while with ix1=" << ix1 << ", ix1l=" << ix1l
00278 << ", ix2=" << ix2 << ", ix2l=" << ix2l << endl;
00279 }
00280
00281 Double_t yprev = -1;
00282
00283 Double_t y = 0;
00284 while((ix1 < ix1l) | (ix2 < ix2l)) {
00285 if (idebug >= 1 ) cout << "----Top of while with ix1=" << ix1
00286 << ", ix1l=" << ix1l << ", ix2=" << ix2
00287 << ", ix2l=" << ix2l << endl;
00288
00289
00290
00291
00292
00293 Int_t i12type = -1;
00294
00295 if ((sigdis1[ix1+1] <= sigdis2[ix2+1] || ix2 == ix2l) && ix1 < ix1l) {
00296 ix1 = ix1 + 1;
00297 while(sigdis1[ix1+1] <= sigdis1[ix1] && ix1 < ix1l) {
00298 ix1 = ix1 + 1;
00299 }
00300 i12type = 1;
00301 } else if (ix2 < ix2l) {
00302 ix2 = ix2 + 1;
00303 while(sigdis2[ix2+1] <= sigdis2[ix2] && ix2 < ix2l) {
00304 ix2 = ix2 + 1;
00305 }
00306 i12type = 2;
00307 }
00308 if (i12type == 1) {
00309 if (idebug >= 3) {
00310 cout << "Pair for i12type=1: " << sigdis2[ix2] << " "
00311 << sigdis1[ix1] << " " << sigdis2[ix2+1] << endl;
00312 }
00313 x1 = axis1->GetBinLowEdge(ix1+1);
00314 y = sigdis1[ix1];
00315 Double_t x20 = axis2->GetBinLowEdge(ix2+1);
00316 Double_t x21 = axis2->GetBinUpEdge(ix2+1);
00317 Double_t y20 = sigdis2[ix2];
00318 Double_t y21 = sigdis2[ix2+1];
00319
00320
00321
00322
00323
00324 if (y21 > y20) {
00325 x2 = x20 + (x21-x20)*(y-y20)/(y21-y20);
00326 }
00327 else {
00328 x2 = x20;
00329 }
00330 } else {
00331 if (idebug >= 3) {
00332 cout << "Pair for i12type=2: " << sigdis1[ix1] << " " << sigdis2[ix2]
00333 << " " << sigdis1[ix1+1] << endl;
00334 }
00335 x2 = axis2->GetBinLowEdge(ix2+1);
00336 y = sigdis2[ix2];
00337 Double_t x10 = axis1->GetBinLowEdge(ix1+1);
00338 Double_t x11 = axis1->GetBinUpEdge(ix1+1);
00339 Double_t y10 = sigdis1[ix1];
00340 Double_t y11 = sigdis1[ix1+1];
00341
00342
00343
00344
00345
00346 if (y11 > y10) {
00347 x1 = x10 + (x11-x10)*(y-y10)/(y11-y10);
00348 } else {
00349 x1 = x10;
00350 }
00351 }
00352
00353
00354
00355
00356
00357
00358
00359 x = wt1*x1 + wt2*x2;
00360 if (y > yprev) {
00361 nx3 = nx3+1;
00362 if (idebug >= 1) {
00363 cout << " ---> y > yprev: i12type=" << i12type << ", nx3="
00364 << nx3 << ", x= " << x << ", y=" << y << ", yprev=" << yprev
00365 << endl;
00366 }
00367 yprev = y;
00368 xdisn[nx3] = x;
00369 sigdisn[nx3] = y;
00370 if(idebug >= 1) {
00371 cout << " ix1=" << ix1 << ", ix2= " << ix2 << ", i12type= "
00372 << i12type << ", sigdis1[ix1]=" << sigdis1[ix1] << endl;
00373 cout << " " << ", nx3=" << nx3 << ", x=" << x << ", y= "
00374 << sigdisn[nx3] << endl;
00375 }
00376 }
00377 }
00378 if (idebug >=3) for (Int_t i=0;i<nx3;i++) {
00379 cout << " nx " << i << " " << xdisn[i] << " " << sigdisn[i] << endl;
00380 }
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391 x = xmaxn;
00392 Int_t ix = nbn;
00393
00394 if (idebug >= 1) cout << "------> Any final bins to set? " << x << " "
00395 << xdisn[nx3] << endl;
00396 while(x >= xdisn[nx3]) {
00397 sigdisf[ix] = sigdisn[nx3];
00398 if (idebug >= 2) cout << " Setting final bins" << ix << " " << x
00399 << " " << sigdisf[ix] << endl;
00400 ix = ix-1;
00401 x = bedgesn[ix];
00402 }
00403 Int_t ixl = ix + 1;
00404 if (idebug >= 1) cout << " Now ixl=" << ixl << " ix=" << ix << endl;
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414 ix = 0;
00415 x = bedgesn[ix+1];
00416 if (idebug >= 1) cout << "Start setting initial bins at x=" << x << endl;
00417 while(x <= xdisn[0]) {
00418 sigdisf[ix] = sigdisn[0];
00419 if (idebug >= 1) cout << " Setting initial bins " << ix << " " << x
00420 << " " << xdisn[1] << " " << sigdisf[ix] << endl;
00421 ix = ix+1;
00422 x = bedgesn[ix+1];
00423 }
00424 Int_t ixf = ix;
00425
00426 if (idebug >= 1)
00427 cout << "Bins left to loop over:" << ixf << "-" << ixl << endl;
00428
00429
00430
00431
00432 Int_t ix3 = 0;
00433 for(ix=ixf;ix<ixl;ix++) {
00434 x = bedgesn[ix];
00435 if (x < xdisn[0]) {
00436 y = 0;
00437 } else if (x > xdisn[nx3]) {
00438 y = 1.;
00439 } else {
00440 while(xdisn[ix3+1] <= x && ix3 < 2*nbn) {
00441 ix3 = ix3 + 1;
00442 }
00443 Double_t dx2=axis2->GetBinWidth(axis2->FindBin(x));
00444 if (xdisn[ix3+1]-x > 1.1*dx2) {
00445 y = sigdisn[ix3+1];
00446 }
00447 else if (xdisn[ix3+1] > xdisn[ix3]) {
00448 y = sigdisn[ix3] + (sigdisn[ix3+1]-sigdisn[ix3])
00449 *(x-xdisn[ix3])/(xdisn[ix3+1]-xdisn[ix3]);
00450 } else {
00451 y = 0;
00452 cout << "Warning - th1fmorph: This probably shoudn't happen! "
00453 << endl;
00454 cout << "Warning - th1fmorph: Zero slope solving x(y)" << endl;
00455 }
00456 }
00457 sigdisf[ix] = y;
00458 if (idebug >= 3) {
00459 cout << ix << ", ix3=" << ix3 << ", xdisn=" << xdisn[ix3] << ", x="
00460 << x << ", next xdisn=" << xdisn[ix3+1] << endl;
00461 cout << " cdf n=" << sigdisn[ix3] << ", y=" << y << ", next point="
00462 << sigdisn[ix3+1] << endl;
00463 }
00464 }
00465
00466
00467
00468
00469 TH1_t *morphedhist = (TH1_t *)gROOT->FindObject(chname);
00470 if (morphedhist) delete morphedhist;
00471 morphedhist = new TH1_t(chname,chtitle,nbn,bedgesn.GetArray());
00472
00473 for(ix=nbn-1;ix>-1;ix--) {
00474 y = sigdisf[ix+1]-sigdisf[ix];
00475 morphedhist->SetBinContent(ix+1,y*morphedhistnorm);
00476 }
00477
00478
00479
00480 delete sigdis1; delete sigdis2;
00481 delete sigdisn; delete xdisn; delete sigdisf;
00482
00483
00484
00485 return(morphedhist);
00486 }
00487
00488
00489 TH1F *th1fmorph(const char *chname,
00490 const char *chtitle,
00491 TH1F *hist1,TH1F *hist2,
00492 Double_t par1,Double_t par2,Double_t parinterp,
00493 Double_t morphedhistnorm,
00494 Int_t idebug)
00495 { return th1fmorph_<TH1F, Float_t>(chname, chtitle, hist1, hist2, par1, par2, parinterp, morphedhistnorm, idebug); }
00496
00497 TH1D *th1fmorph(const char *chname,
00498 const char *chtitle,
00499 TH1D *hist1,TH1D *hist2,
00500 Double_t par1,Double_t par2,Double_t parinterp,
00501 Double_t morphedhistnorm,
00502 Int_t idebug)
00503 { return th1fmorph_<TH1D, Double_t>(chname, chtitle, hist1, hist2, par1, par2, parinterp, morphedhistnorm, idebug); }