1 /**************************************************************************
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
7 * Permission to use, copy, modify and distribute this software and its *
8 * documentation strictly for non-commercial purposes is hereby granted *
9 * without fee, provided that the above copyright notice appears in all *
10 * copies and that both the copyright notice and this permission notice *
11 * appear in the supporting documentation. The authors make no claims *
12 * about the suitability of this software for any purpose. It is *
13 * provided "as is" without express or implied warranty. *
14 **************************************************************************/
16 /* Origin: Alberica Toia, CERN, Alberica.Toia@cern.ch */
18 ///////////////////////////////////////////////////////////////////////////////
20 // class to determine centrality percentiles from 1D distributions //
22 ///////////////////////////////////////////////////////////////////////////////
34 #include <TGraphErrors.h>
37 #include <TStopwatch.h>
39 #include <TDatabasePDG.h>
41 #include "AliCentralityGlauberFit.h"
44 ClassImp(AliCentralityGlauberFit)
46 //______________________________________________________________________________
47 AliCentralityGlauberFit::AliCentralityGlauberFit(const char *filename) :
80 fAncfilename("ancestor_hists.root"),
83 // Standard constructor.
85 if (filename) { // glauber file
86 f = TFile::Open(filename);
87 fGlauntuple = (TNtuple*) f->Get("nt_p_Pb");
88 fGlauntuple->SetBranchAddress("Npart",&fNpart);
89 fGlauntuple->SetBranchAddress("Ncoll",&fNcoll);
90 fGlauntuple->SetBranchAddress("B",&fB);
91 fGlauntuple->SetBranchAddress("tAA",&fTaa);
96 //--------------------------------------------------------------------------------------------------
97 void AliCentralityGlauberFit::SetRangeToFit(Double_t fmultmin, Double_t fmultmax)
105 //--------------------------------------------------------------------------------------------------
106 void AliCentralityGlauberFit::SetRangeToScale(Double_t fscalemin)
108 // Set range where to scale simulated histo to data
113 //--------------------------------------------------------------------------------------------------
114 void AliCentralityGlauberFit::SetGlauberParam(
131 // Set Glauber parameters.
137 fAlphahigh=alphahigh;
140 fSigmahigh=sigmahigh;
149 //--------------------------------------------------------------------------------------------------
150 void AliCentralityGlauberFit::MakeFits()
158 //FILE* fTxt = fopen ("parameters.txt","w");
160 // open inrootfile, outrootfile
161 std::cout << "input file " << fInrootfilename << std::endl;
162 std::cout << "output file " << fOutrootfilename << std::endl;
163 inrootfile = new TFile(fInrootfilename,"OPEN");
164 outrootfile = new TFile(fOutrootfilename,"RECREATE");
166 // loop over all distribution names
167 std::vector<TString>::const_iterator hni;
168 for(hni=fHistnames.begin(); hni!=fHistnames.end(); hni++) {
169 hDATA = (TH1F*) (inrootfile->Get(*hni));
171 TList *list = (TList*) (inrootfile->Get("CentralityStat"));
172 //TList *list = (TList*) (inrootfile->Get("VZEROEquaFactorStat"));
173 hDATA = (TH1F*) (list->FindObject(*hni));
175 hDATA->Rebin(fRebinFactor);
176 //TH1F *hGLAU = new TH1F("hGLAU","hGLAU",hDATA->GetNbinsX(),0,hDATA->GetNbinsX()*hDATA->GetBinWidth(1));
178 Double_t chi2min = 9999999.0;
181 Double_t sigma_min=-1;
182 Double_t alpha_min=-1;
184 Double_t alpha, k, sigma, bog, CP, chi2;
186 for (Int_t nCP=0;nCP<fNCP;nCP++) {
187 CP = fCPlow + ((Double_t) nCP ) * (fCPhigh - fCPlow ) / fNCP;
189 for (Int_t nbog=0;nbog<fNbog;nbog++) {
190 bog = fBoglow + ((Double_t) nbog ) * (fBoghigh - fBoglow ) / fNbog;
192 for (Int_t nsigma=0;nsigma<fNsigma;nsigma++) {
193 sigma = fSigmalow + ((Double_t) nsigma ) * (fSigmahigh - fSigmalow ) / fNsigma;
195 for (Int_t nalpha=0;nalpha<fNalpha;nalpha++) {
196 alpha = fAlphalow + ((Double_t) nalpha ) * (fAlphahigh - fAlphalow ) / fNalpha;
198 for (Int_t nk=0; nk<fNk; nk++) {
199 k = fKlow + ((Double_t) nk ) * (fKhigh - fKlow ) / fNk;
201 thistGlau = GlauberHisto(k,alpha,sigma,bog,CP,hDATA,kFALSE);
202 chi2 = CalculateChi2(hDATA,thistGlau);
203 //cout << "chi2 " << chi2<< endl;
204 if ( chi2 < chi2min ) {
217 thistGlau = GlauberHisto(k_min,alpha_min,sigma_min,bog_min,CP_min, hDATA,kTRUE);
220 hGLAU = (TH1F *) thistGlau->Clone("hGLAU");
221 hGLAU->SetName( ((TString)hDATA->GetName()).Append(Form("_GLAU")));
222 hGLAU->SetTitle( ((TString)hDATA->GetName()).Append(Form("_GLAU_%.3f_%.3f_%.3f_%.3f_%.3f",
223 k_min,alpha_min,sigma_min,bog_min,CP_min)));
225 Double_t mcintegral = hGLAU->Integral(hGLAU->FindBin(fScalemin),hGLAU->GetNbinsX());
226 Double_t scale = (hDATA->Integral(hDATA->FindBin(fScalemin),hDATA->GetNbinsX())/mcintegral);
227 std::cout << hGLAU->FindBin(fScalemin) << " " << hGLAU->Integral(hGLAU->FindBin(fScalemin),hGLAU->GetNbinsX()) << std::endl;
228 std::cout << hDATA->FindBin(fScalemin) << " " << hDATA->Integral(hDATA->FindBin(fScalemin),hDATA->GetNbinsX()) << std::endl;
231 SaveHisto(hDATA,hGLAU,outrootfile);
234 std::cout << "chi2 min is " << chi2min << std::endl;
235 std::cout << "fitted " << hGLAU->Integral(hGLAU->FindBin(fMultmin),
236 hGLAU->FindBin(fMultmax))/hGLAU->Integral()
237 << " of the total cross section" << std::endl;
242 // close inrootfile, outrootfile
244 outrootfile->Close();
248 //--------------------------------------------------------------------------------------------------
249 TH1F *AliCentralityGlauberFit::GlauberHisto(Double_t k, Double_t alpha, Double_t sigma, Double_t bog, Double_t CP,
250 TH1F *hDATA, Bool_t save)
252 // Get Glauber histogram.
253 static TH1F *h1 = (TH1F*)hDATA->Clone();
255 h1->SetName(Form("fit_%.3f_%.3f",k,alpha));
257 TFile *outFile = NULL;
258 TNtuple *ntuple = NULL;
261 outFile = new TFile(fOutntuplename,"RECREATE");
262 ntuple = new TNtuple("gnt", "Glauber ntuple", "Npart:Ncoll:B:tAA:ntot:nbn:ngn");
267 nents = fGlauntuple->GetEntries();
269 for (Int_t i=0;i<fNevents;++i) {
271 fGlauntuple->GetEntry(i % nents);
277 // Slow Nucleon Model from Chiara
279 Double_t ntot, nbn, ngn, nbp, ngp;
280 MakeSlowNucleons2(fNcoll,alpha,k,bog,CP, nbn,ngn,nbp,ngp);
283 //conversion to energy *13.5; // conversion to energy------------------------
284 //Double_t Engn, Enbn;
285 //Engn = ConvertToEnergy(0.05);
286 //Enbn = ConvertToEnergy(0.005);
288 //Engn = 1;//gRandom->Gaus(13.5, TMath::Sqrt(13.5));
289 //Enbn = 1;//gRandom->Gaus(13.5, TMath::Sqrt(13.5));
291 //Enbn =(int)nbn*Enbn;
292 //Engn =(int)ngn*Engn;
295 //for (int i=0; i<(int)nbn; i++){
296 // Enbn += ConvertToEnergy(0.005);
298 //for (int i=0; i<(int)ngn; i++){
299 // Engn += ConvertToEnergy(0.05);
302 //cout << "GRAY " << Engn << " BLACK " << Enbn << endl;
305 n=alpha*ngn+alpha*nbn;
306 // n=alpha*ngp+alpha*nbp;
307 //----------------------------------------
309 //------ experimental resolution -> Gaussian smearing ------------------------------------
311 //if (n>0) resexp = 1./TMath::Sqrt(n)*sigma*gRandom->Gaus(0.0,1.0);
315 if (n>0)resexp = sigma*TMath::Sqrt(n)/2;
317 ntot = (Int_t)(gRandom->Gaus(n,resexp));
318 //----------------------------------------
320 // non-lineary effect -------------------------------
322 ntot = ntot + k*ntot*ntot;
324 //cout << ngn << " " << nbn << " " << ntot << endl;
329 ntuple->Fill(fNpart,fNcoll,fB,fTaa,ntot,nbn,ngn);
340 //--------------------------------------------------------------------------------------------------
341 Double_t AliCentralityGlauberFit::CalculateChi2(TH1F *hDATA, TH1F *thistGlau)
343 // Note that for different values of neff the mc distribution is identical, just re-scaled below
344 // normalize the two histogram, scale MC up but leave data alone - that preserves error bars !!!!
346 Int_t lowchibin = hDATA->FindBin(fMultmin);
347 Int_t highchibin = hDATA->FindBin(fMultmax);
349 Double_t mcintegral = thistGlau->Integral(1,thistGlau->GetNbinsX());
350 Double_t scale = (hDATA->Integral(1,hDATA->GetNbinsX())/mcintegral);
351 thistGlau->Scale(scale);
353 // calculate the chi2 between MC and real data over some range ????
356 for (Int_t i=lowchibin; i<=highchibin; i++) {
357 if (hDATA->GetBinContent(i) < 1.0) continue;
358 Double_t diff = TMath::Power((thistGlau->GetBinContent(i) - hDATA->GetBinContent(i)),2);
359 diff = diff / (TMath::Power(hDATA->GetBinError(i),2) + TMath::Power(thistGlau->GetBinError(i),2));
362 chi2 = chi2 / (highchibin - lowchibin + 1);
365 // "-2 log likelihood ratio(mu;n) = 2[(mu - n) + n ln(n/mu)]"
367 std::cout << "LL" << std::endl;
370 for (Int_t i=lowchibin; i<=highchibin; i++) {
371 Double_t data = hDATA ->GetBinContent(i);
372 Double_t mc = thistGlau->GetBinContent(i);
373 Int_t idata = TMath::Nint(data);
374 if (mc < 1.e-9) mc = 1.e-9;
375 Double_t fsub = - mc + idata * TMath::Log(mc);
378 for(Int_t istep = 0; istep < idata; istep++){
380 fobs += TMath::Log(istep);
390 //--------------------------------------------------------------------------------------------------
391 void AliCentralityGlauberFit::SaveHisto(TH1F *hist1, TH1F *hist2, TFile *outrootfile)
400 //--------------------------------------------------------------------------------------------------
401 void AliCentralityGlauberFit::MakeSlowNucleons(Int_t ncoll, Double_t alpha, Double_t k, Double_t &nbn, Double_t &ngn)
403 // from AliGenSlowNucleonModelExp (Chiara Oppedisano)
404 // Return the number of black and gray nucleons
406 // Number of collisions
410 Float_t nu = (Float_t) ncoll;
412 // Mean number of gray nucleons
413 Float_t nGray = alpha * nu;
414 Float_t nGrayNeutrons = nGray * fN / (fN + fP);
415 Float_t nGrayProtons = nGray - nGrayNeutrons;
417 // Mean number of black nucleons
419 if(!fApplySaturation || (fApplySaturation && nGray<fnGraySaturation)) nBlack = k * nu;
420 else if(fApplySaturation && nGray>=fnGraySaturation) nBlack = fnBlackSaturation;
421 Float_t nBlackNeutrons = nBlack * 0.84;
422 Float_t nBlackProtons = nBlack - nBlackNeutrons;
424 // Actual number (including fluctuations) from binomial distribution
425 Double_t p, ngp, nbp;
428 p = nGrayNeutrons/fN;
429 ngn = gRandom->Binomial((Int_t) fN, p);
433 ngp = gRandom->Binomial((Int_t) fP, p);
436 p = nBlackNeutrons/fN;
437 nbn = gRandom->Binomial((Int_t) fN, p);
440 p = nBlackProtons/fP;
441 nbp = gRandom->Binomial((Int_t) fP, p);
447 //--------------------------------------------------------------------------------------------------
448 void AliCentralityGlauberFit::MakeSlowNucleons2(Int_t ncoll, Double_t alpha, Double_t k, Double_t bog, Double_t CP, Double_t &nbn, Double_t &ngn, Double_t &nbp, Double_t &ngp)
449 //void AliCentralityGlauberFit::MakeSlowNucleons2(Int_t ncoll, Double_t alpha, Double_t k, Double_t bog, Double_t CP, Double_t &nbn, Double_t &ngn)
451 // from AliGenSlowNucleonModelExp (Chiara Oppedisano)
453 // Return the number of black and gray nucleons
455 // Number of collisions
457 // based on E910 model ================================================================
462 Float_t nu = (Float_t) ncoll;
464 nu = nu+1.*gRandom->Rndm();
468 Float_t poverpd = 0.843;
469 Float_t zAu2zPb = 82./79.;
470 Float_t nGrayp = (-0.27 + 0.63 * nu - 0.0008 *nu *nu)*poverpd*zAu2zPb;
474 ngp = gRandom->Binomial((Int_t) fP, p);
475 //ngp = gRandom->Gaus(nGrayp, TMath::Sqrt(fP*p*(1-p)));
479 //Float_t blackovergray = 3./7.;// from spallation
480 //Float_t blackovergray = 0.65; // from COSY
481 Float_t blackovergray = bog;
482 Float_t nBlackp = blackovergray*nGrayp;
485 nbp = gRandom->Binomial((Int_t) fP, p);
486 //nbp = gRandom->Gaus(nBlackp, TMath::Sqrt(fP*p*(1-p)));
487 if(nBlackp<0.) nbp=0;
490 nGrayp = -0.836 + 0.9112 *nu - 0.05381 *nu *nu;
491 nBlackp = blackovergray*nGrayp;
496 Float_t nGrayNeutrons = 0.;
497 Float_t nBlackNeutrons = 0.;
498 //Float_t cp = (nGrayp+nBlackp)/0.24;
499 Float_t cp = (nGrayp+nBlackp)/CP;
502 // //Float_t nSlow = 51.5+469.2/(-8.762-cp);
503 // Float_t nSlow = 60.0+469.2/(-8.762-cp);
504 // //if(cp<2.5) nSlow = 1+(9.9-1)/(2.5-0)*(cp-0);
505 // if(cp<3.) nSlow = 0.+(11.6-0.)/(3.-0.)*(cp-0.);
507 // nGrayNeutrons = nSlow * 0.1;
508 // nBlackNeutrons = nSlow - nGrayNeutrons;
511 Float_t paramnSlow[3] = {60., 469.2, 8.762};
512 Float_t nSlow = paramnSlow[0]+paramnSlow[1]/(-paramnSlow[2]-cp);
513 float paramRetta = paramnSlow[0]+paramnSlow[1]/(-paramnSlow[2]-3);
514 if(cp<3.) nSlow = 0.+(paramRetta-0.)/(3.-0.)*(cp-0.);
516 nGrayNeutrons = nSlow * 0.1;
517 nBlackNeutrons = nSlow - nGrayNeutrons;
520 // Sikler "pasturato"
521 nGrayNeutrons = 0.47 * 2.3 * nu; // fAlphaGray=2.3
522 nBlackNeutrons = 0.88 * 3.6 * nu; // fAlphaBlack=3.6
523 printf("nslowp=0 -> ncoll = %1.0f -> ngrayn = %1.0f nblackn = %1.0f \n", nu, nGrayNeutrons, nBlackNeutrons);
526 p = nGrayNeutrons/fN;
527 //ngn = gRandom->Binomial((Int_t) fN, p);
528 ngn = gRandom->Gaus(nGrayNeutrons, TMath::Sqrt(fN*p*(1-p)));
531 p = nBlackNeutrons/fN;
532 //nbn = gRandom->Binomial((Int_t) fN, p);
533 nbn = gRandom->Gaus(nBlackNeutrons, TMath::Sqrt(fN*p*(1-p)));
536 Double_t AliCentralityGlauberFit::ConvertToEnergy(Double_t T)
538 TDatabasePDG * pdg = TDatabasePDG::Instance();
539 const Double_t kMassNeutron = pdg->GetParticle(kNeutron)->Mass();
542 Double_t m, p, pmax, ekin, f;
544 pmax = TMath::Sqrt(2*T*(T+TMath::Sqrt(T*T+m*m)));
548 p = gRandom->Rndm() * fPmax;
549 f = Maxwell(m, p, T) / Maxwell(m , pmax, T);
551 while(f < gRandom->Rndm());
553 return 13.5*TMath::Sqrt(p*p+m*m);
556 Double_t AliCentralityGlauberFit::Maxwell(Double_t m, Double_t p, Double_t T)
558 /* Relativistic Maxwell-distribution */
560 ekin = TMath::Sqrt(p*p+m*m)-m;
561 return (p*p * exp(-ekin/T));