+
+ // Fill the last rows of fHistStatistics before saving
+ if (fComputeBG) {
+ AliInfo("BG estimate assumes that for a given run you only have A and C triggers separately or"
+ " toghether as a AC class! Make sure this assumption holds in your case");
+
+ // use an anum for the different trigger classes, to make loops easier to read
+ enum {kClassB =0 , kClassA, kClassC, kClassAC, kClassE, kNClasses};
+ const char * classFlags[] = {"B", "A", "C", "AC", "E"}; // labels
+
+ UInt_t * rows[kNClasses] = {0}; // Array of matching rows
+ Int_t nrows[kNClasses] = {0};
+ // Get rows matching the requested trigger bits for all trigger classes
+ for(Int_t iTrigClass = 0; iTrigClass < kNClasses; iTrigClass++){
+ nrows[iTrigClass] = GetStatRow(classFlags[iTrigClass],fComputeBG,&rows[iTrigClass]);
+ }
+
+ // 0. Determine the ratios of triggers E/B, A/B, C/B from the stat histogram
+ // Those are used to rescale the different classes to the same number of bx ids
+ // TODO: pass names of the rows for B, CA and E and look names of the rows. How do I handle the case in which both AC are in the same row?
+ Int_t nBXIds[kNClasses] = {0};
+ // cout <<"Computing BG:" << endl;
+
+ for(Int_t iTrigClass = 0; iTrigClass < kNClasses; iTrigClass++){
+ for(Int_t irow = 0; irow < nrows[iTrigClass]; irow++) {
+ if(irow==0) cout << "- Class " << classFlags[iTrigClass] << endl;
+ for (Int_t j=1; j<=fHistBunchCrossing->GetNbinsX(); j++) {
+ if (fHistBunchCrossing->GetBinContent(j, rows[iTrigClass][irow]) > 0) {
+ nBXIds[iTrigClass]++;
+ }
+ }
+ if(nBXIds[iTrigClass]>0) cout << " Using row " << rows[iTrigClass][irow] << ": "
+ << fHistBunchCrossing->GetYaxis()->GetBinLabel(rows[iTrigClass][irow])
+ << " (nBXID "<< nBXIds[iTrigClass] << ")"<< endl;
+
+ }
+
+ }
+
+ Float_t ratioToB[kNClasses];
+ ratioToB[kClassE] = nBXIds[kClassE] >0 ? Float_t(nBXIds[kClassB])/nBXIds[kClassE] : 0;
+ ratioToB[kClassA] = nBXIds[kClassA] >0 ? Float_t(nBXIds[kClassB])/nBXIds[kClassA] : 0;
+ ratioToB[kClassC] = nBXIds[kClassC] >0 ? Float_t(nBXIds[kClassB])/nBXIds[kClassC] : 0;
+ ratioToB[kClassAC] = nBXIds[kClassAC] >0 ? Float_t(nBXIds[kClassB])/nBXIds[kClassAC] : 0;
+ Printf("Ratio between the BX ids in the different trigger classes:");
+ Printf(" B/E = %d/%d = %f", nBXIds[kClassB],nBXIds[kClassE], ratioToB[kClassE] );
+ Printf(" B/A = %d/%d = %f", nBXIds[kClassB],nBXIds[kClassA], ratioToB[kClassA] );
+ Printf(" B/C = %d/%d = %f", nBXIds[kClassB],nBXIds[kClassC], ratioToB[kClassC] );
+ Printf(" B/AC = %d/%d = %f", nBXIds[kClassB],nBXIds[kClassAC],ratioToB[kClassAC]);
+ Int_t nHistStat = 2;
+
+ // 1. loop over all cols
+ for(Int_t iHistStat = 0; iHistStat < nHistStat; iHistStat++){
+ Int_t ncol = fHistStatistics[iHistStat]->GetNbinsX();
+ Float_t good1 = 0;
+ for(Int_t icol = 1; icol <= ncol; icol++) {
+ Int_t nEvents[kNClasses] = {0}; // number of events should be reset at every column
+ // For all trigger classes, add up over row matching trigger mask (as selected before)
+ for(Int_t iTrigClass = 0; iTrigClass < kNClasses; iTrigClass++){
+ for(Int_t irow = 0; irow < nrows[iTrigClass]; irow++) {
+ nEvents[iTrigClass] += (Int_t) fHistStatistics[iHistStat]->GetBinContent(icol,rows[iTrigClass][irow]);
+ }
+ // cout << "Events " << classFlags[iTrigClass] << " ("<<icol<<") " << nEvents[iTrigClass] << endl;
+ }
+ if (nEvents[kClassB]>0) {
+ Float_t acc = ratioToB[kClassE]*nEvents[kClassE];
+ Double_t accErr = TMath::Sqrt(ratioToB[kClassE]*ratioToB[kClassE]*nEvents[kClassE]);
+ // Int_t bg = cint1A + cint1C - 2*acc;
+
+ // If intensity measurements are available, they already
+ // contain the scaling for BX ratios, so we reset the
+ // ratioToB entries
+ if(icol == 1) {
+ if(fBIFactorAC > 0 || fBIFactorA > 0 || fBIFactorC > 0) {
+ if (fBIFactorAC <= 0 && (fBIFactorA <= 0 || fBIFactorC <= 0)) {
+ AliError("Not all intensities set!, assuming equal intensities");
+ fBIFactorA = 1;
+ fBIFactorC = 1;
+ fBIFactorAC = 1;
+ } else {
+ AliInfo("Using ratio of number of bunch crossing embedded in the intensity measurements");
+ ratioToB[kClassA] = ratioToB[kClassA] >0 ? 1 : 0;
+ ratioToB[kClassC] = ratioToB[kClassC] >0 ? 1 : 0;
+ ratioToB[kClassAC] = ratioToB[kClassAC] >0 ? 1 : 0;
+ AliInfo(Form(" - BI Factor A: %f", fBIFactorA ));
+ AliInfo(Form(" - BI Factor C: %f", fBIFactorC ));
+ AliInfo(Form(" - BI Factor AC: %f", fBIFactorAC ));
+
+ }
+ } else {
+ AliWarning("Intensities not set!, assuming equal intensities");
+ fBIFactorA = 1;
+ fBIFactorC = 1;
+ fBIFactorAC = 1;
+ }
+ }
+ // Assuming that for a given class the triggers are either recorded as A+C or AC
+ Float_t bg = nEvents[kClassAC] > 0 ?
+ fBIFactorAC*(ratioToB[kClassAC]*nEvents[kClassAC] - 2*acc):
+ fBIFactorA* (ratioToB[kClassA]*nEvents[kClassA]-acc) +
+ fBIFactorC* (ratioToB[kClassC]*nEvents[kClassC]-acc) ;
+
+ // cout << "-----------------------" << endl;
+ // cout << "Factors: " << fBIFactorA << " " << fBIFactorC << " " << fBIFactorAC << endl;
+ // cout << "Ratios: " << ratioToB[kClassA] << " " << ratioToB[kClassC] << " " << ratioToB[kClassAC] << endl;
+ // cout << "Evts: " << nEvents[kClassA] << " " << nEvents[kClassC] << " " << nEvents[kClassAC] << " " << nEvents[kClassB] << endl;
+ // cout << "Acc: " << acc << endl;
+ // cout << "BG: " << bg << endl;
+ // cout << " " << fBIFactorA* (ratioToB[kClassA]*nEvents[kClassA]-acc) <<endl;
+ // cout << " " << fBIFactorC* (ratioToB[kClassC]*nEvents[kClassC]-acc) <<endl;
+ // cout << " " << fBIFactorAC*(ratioToB[kClassAC]*nEvents[kClassAC] - 2*acc) << endl;
+ // cout << "-----------------------" << endl;
+
+ Float_t good = Float_t(nEvents[kClassB]) - bg - acc;
+ if (icol ==1) good1 = good;
+ // Float_t errGood = TMath::Sqrt(2*(nEvents[kClassA]+nEvents[kClassC]+nEvents[kClassE]));// Error on the number of goods assuming only bg fluctuates
+ // DeltaG^2 = B + FA^2 A + FC^2 C + Ratio^2 (FA+FC-1)^2 E.
+ Float_t errGood = nEvents[kClassAC] > 0 ?
+ TMath::Sqrt( nEvents[kClassB] +
+ fBIFactorAC*fBIFactorAC*ratioToB[kClassAC]*ratioToB[kClassAC]*nEvents[kClassAC] +
+ ratioToB[kClassE] * ratioToB[kClassE] *
+ (fBIFactorAC - 1)*(fBIFactorAC - 1)*nEvents[kClassE]) :
+ TMath::Sqrt( nEvents[kClassB] +
+ fBIFactorA*fBIFactorA*ratioToB[kClassA]*ratioToB[kClassA]*nEvents[kClassA] +
+ fBIFactorC*fBIFactorC*ratioToB[kClassC]*ratioToB[kClassC]*nEvents[kClassC] +
+ ratioToB[kClassE] * ratioToB[kClassE] *
+ (fBIFactorA + fBIFactorC - 1)*(fBIFactorA + fBIFactorC - 1)*nEvents[kClassE]);
+
+ Float_t errBG = nEvents[kClassAC] > 0 ?
+ TMath::Sqrt(fBIFactorAC*fBIFactorAC*ratioToB[kClassAC]*ratioToB[kClassAC]*nEvents[kClassAC]+
+ 4*ratioToB[kClassE]*ratioToB[kClassE]*(fBIFactorAC*fBIFactorAC)*nEvents[kClassE]) :
+ TMath::Sqrt(fBIFactorA*fBIFactorA*ratioToB[kClassA]*ratioToB[kClassA]*nEvents[kClassA]+
+ fBIFactorC*fBIFactorC*ratioToB[kClassC]*ratioToB[kClassC]*nEvents[kClassC]+
+ ratioToB[kClassE]*ratioToB[kClassE]*(fBIFactorA+fBIFactorC)*(fBIFactorA+fBIFactorC)*nEvents[kClassE]);
+
+
+ fHistStatistics[iHistStat]->SetBinContent(icol,fBGStatOffset+kStatRowAllB, nEvents[kClassB]);
+ fHistStatistics[iHistStat]->SetBinContent(icol,fBGStatOffset+kStatRowAllAC,nEvents[kClassA]+nEvents[kClassC]+nEvents[kClassAC]);
+ fHistStatistics[iHistStat]->SetBinContent(icol,fBGStatOffset+kStatRowAllE, nEvents[kClassE]);
+
+ fHistStatistics[iHistStat]->SetBinContent(icol,fBGStatOffset+kStatRowBG,bg);
+ fHistStatistics[iHistStat]->SetBinError (icol,fBGStatOffset+kStatRowBG,errBG);
+ fHistStatistics[iHistStat]->SetBinContent(icol,fBGStatOffset+kStatRowAcc,acc);
+ fHistStatistics[iHistStat]->SetBinError (icol,fBGStatOffset+kStatRowAcc,accErr);
+ fHistStatistics[iHistStat]->SetBinContent(icol,fBGStatOffset+kStatRowGood,good);
+ fHistStatistics[iHistStat]->SetBinError (icol,fBGStatOffset+kStatRowGood,errGood);
+
+#ifdef VERBOSE_STAT
+ //kStatRowBG=0,kStatRowAcc,kStatRowBGFrac,kStatRowAccFrac,kStatRowErrGoodFrac,kStatRowGoodFrac,kStatRowGood,kStatRowErrGood
+ Float_t accFrac = Float_t(acc) / nEvents[kClassB] *100;
+ Float_t errAccFrac= Float_t(accErr) / nEvents[kClassB] *100;
+ Float_t bgFrac = Float_t(bg) / nEvents[kClassB] *100;
+ Float_t goodFrac = Float_t(good) / good1 *100;
+ Float_t errGoodFrac = errGood/good1 * 100;
+ Float_t errFracBG = bg > 0 ? TMath::Sqrt((errBG/bg)*(errBG/bg) + 1/nEvents[kClassB])*bgFrac : 0;
+ fHistStatistics[iHistStat]->SetBinContent(icol,fBGStatOffset+kStatRowBGFrac,bgFrac);
+ fHistStatistics[iHistStat]->SetBinError (icol,fBGStatOffset+kStatRowBGFrac,errFracBG);
+ fHistStatistics[iHistStat]->SetBinContent(icol,fBGStatOffset+kStatRowAccFrac,accFrac);
+ fHistStatistics[iHistStat]->SetBinError (icol,fBGStatOffset+kStatRowAccFrac,errAccFrac);
+ fHistStatistics[iHistStat]->SetBinContent(icol,fBGStatOffset+kStatRowGoodFrac,goodFrac);
+ fHistStatistics[iHistStat]->SetBinContent(icol,fBGStatOffset+kStatRowErrGoodFrac,errGoodFrac);
+ fHistStatistics[iHistStat]->SetBinContent(icol,fBGStatOffset+kStatRowErrGood,errGood);
+#endif
+ }
+ }
+ }
+ for (Int_t iTrigClass = 0; iTrigClass < kNClasses; iTrigClass++){
+ delete [] rows[iTrigClass];
+ }
+ } // end of ComputeBackground
+
+ fHistStatistics[0]->Write();
+ fHistStatistics[1]->Write();
+ if(fHistBunchCrossing ) fHistBunchCrossing ->Write();
+ if(fHistTriggerPattern) fHistTriggerPattern->Write();