TCanvas* pHitSpecPos( )
{
  TCanvas* c = new TCanvas("cHitSpecPos","cHitSpecPos",1000,1100);
  c->Divide(2,2);
  TVirtualPad* p; TH2D *h;
  TText t; t.SetTextColor(4);

  p =c->cd(1); p->SetLogy(); p->SetGrid(1,0);
  h = (TH2D*)gROOT->FindObject("hHitSpec_PtVsPhi_BarMinus"); 
  h->GetYaxis()->SetRange(4,33);
  h->DrawCopy("box");
  t.DrawTextNDC(0.17,0.15, "BARREL MU MINUS");

  p =c->cd(2); p->SetLogy(); p->SetGrid(1,0);
  h = (TH2D*)gROOT->FindObject("hHitSpec_PtVsPhi_BarPlus"); 
  h->GetYaxis()->SetRange(4,32);
  h->DrawCopy("box");
  t.DrawTextNDC(0.17,0.15, "BARREL MU PLUS");

  p =c->cd(3); p->SetLogy(); p->SetGrid(1,0);
  h = (TH2D*)gROOT->FindObject("hHitSpec_PtVsPhi_EndMinus"); 
  h->GetYaxis()->SetRange(4,32);
  h->DrawCopy("box");
  t.DrawTextNDC(0.17,0.15, "ENDCAP MU MINUS");

  p =c->cd(4); p->SetLogy(); p->SetGrid(1,0);
  h = (TH2D*)gROOT->FindObject("hHitSpec_PtVsPhi_EndPlus"); 
  h->GetYaxis()->SetRange(4,32);
  h->DrawCopy("box");
  t.DrawTextNDC(0.17,0.15, "ENDCAP MU PLUS");

  return c;
}
예제 #2
0
void PlotImages()
{
gStyle->SetOptStat(0);
gStyle->SetPadRightMargin(0.2);
string filename[1];
char buffer[100];
char buffertext[100];

for (int seed=55; seed<56; seed++)
  {
    int n=sprintf(buffer, "/home/les67/locust_faketrack_waterfall.root");

    const char *file = buffer;

    TFile* f = TFile::Open(file);
    if (!((!f)||f->IsZombie()))
    {

    TH2D* hspectrogram = GetSpectrogram(file);
    TH2D* hlabels = GetLabels(hspectrogram, 40e-21);  // threshold for labeling goes here.
//    TGraph* grlabels = GetLabelGraph(hlabels);
//    PrintLabels(grlabels);  // print labels to terminal.

    hspectrogram->GetXaxis()->SetRangeUser(0.,0.02);
    hspectrogram->GetYaxis()->SetRangeUser(149.e6, 170.e6);

    TCanvas *c = new TCanvas;
    n=sprintf(buffertext, "hspectrogram_%d.png", seed);
    const char *pngname = buffertext;
    hspectrogram->GetYaxis()->SetTitleOffset(1.25);
    hspectrogram->DrawCopy("colz");

/*
    grlabels->SetMarkerColor(2);
    grlabels->SetMarkerStyle(8);
    grlabels->SetMarkerSize(0.6);
    grlabels->SetLineWidth(3.);
    grlabels->SetLineColor(2);
    grlabels->Draw("psame");
*/


 /*  
    TImage *img = TImage::Create();
    img->FromPad(c);
    img->WriteImage(pngname);
    delete img;
    delete hspectrogram;
    delete c;
*/
    f->Close();
    }

  }

}
TCanvas* pHitSpecDet(const std::string& s)
{
  TCanvas* c = new TCanvas( ("HitSpecDet"+s).c_str(), ("HitSpecDet"+s).c_str(), -2);
  c->SetLogx();
  TH2D* h = (TH2D*)gROOT->FindObject(s.c_str());
  h->GetXaxis()->SetRange(4,32);
  std::stringstream str;
  str<<h->GetTitle();
  TText t;
  t.SetTextColor(4);
  t.SetTextAlign(11);
  t.SetTextSize(0.035);
  h->DrawCopy("box");
  t.DrawTextNDC(0.17,0.2, str.str().c_str());
  return c;
}
예제 #4
0
void NewCosmicstest(){
	//gROOT->Reset();	
	
	TStopwatch *clock0 = new TStopwatch();
	TFile *fout = new TFile("Cosmictest.root","RECREATE");
	bool high = 1;
	
	//Float_t z0 = 1400;
	Float_t z0 = 0;
	Float_t yTop = 600;
	Float_t xTop = 300;
	Float_t zTop = 3650;
	
	Float_t xdist = 3000;
	Float_t zdist = 9000;
	
	TH2D *StartXZ = new TH2D("xz","xz;x[cm];z[cm]",30,-(xdist/2),xdist/2,90,z0 - 4500,z0 + 4500);
	TH1D *StartTheta = new TH1D("#theta","#theta; #theta_Zenith",100,0,2);
	TH1D *StartPhi = new TH1D("#phi","#phi; #phi",50,0,7);
	TH1D *StartPHigh = new TH1D("PHigh","P; P[GeV]",100,-1,3);
	TH1D *StartP = new TH1D("P","P;P[GeV]",100,-1,3);
	TH1D *StartPLow = new TH1D("PLow","P;P[GeV]",100,-1,3);
	//TH1D *StartP = new TH1D("P","P;P[GeV]",100,0.1,1000);
	BinLogX(StartP);
	BinLogX(StartPHigh);
	BinLogX(StartPLow);
	
	TH2D *StartPTheta = new TH2D("P,Theta","P-Theta;P[GeV];#theta",150,-1,3,50,0,2);
	BinLogX(StartPTheta);
	
	TH2D *MCXZ = new TH2D("MCxz","xz;x[cm];z[cm]",30,-(xdist/2),xdist/2,90,z0 - 4500,z0 + 4500);
	TH1D *MCTheta = new TH1D("MC#theta","#theta; #theta",100,0,2);
	TH1D *MCPhi = new TH1D("MC#phi","#phi, #phi",50,0,7);
	
	TH1I *MCnTry = new TH1I("nTry","nTry",100,4.6,5);
	
	Double_t totalweightsum=0;
	Double_t px,py,pz,x,y,z,w, weighttest, weight;
	Int_t nTry,nInside,nEvent,nTest;	
	Co3Rng *fRandomEngine = new Co3Rng();
	
	int EVENTS = 400000;
	Int_t kmax = 40000;
	float weight1,weight1Low,weight1High;
	weight1Low = 123*xdist*zdist/EVENTS/10000; // expected #muons per spill/ #simulated events per spill 174*30*90/500000
	cout<<weight1Low<<endl;
	
	double I = fRandomEngine->fSpectrumH->Integral(100,1000);
	weight1High = 2*TMath::Pi()/3*I*xdist*zdist/EVENTS/10000;
		//weight2 = 900/I; // 1/(mean momentum weight), P_max-P_min/(3*0.3044/2pi)
	
	cout<< weight1High<<endl;
	Float_t weight3 = 4.833931503; // MC average of nTry/nEvents 4.833949997 +- 0.000010494			
	weight1 = 1;								
	weight = weight1 / weight3;
	
	nInside = 0; nEvent = 0; nTest = 0; weighttest = 0;
	y = 1900; //20m over beam axis

	w = weight/kmax;
	clock0->Start();
	for(Int_t k = 0;k<kmax;k++){
		cout<<k<<endl;
		nTry =0;
		for(Int_t i=0;i<EVENTS;i++){
		   Bool_t hit = 0;   
		   do{
				// shower characteristics
			   double phi = fRandomEngine->Uniform(0,2*TMath::Pi());
			   double theta = fRandomEngine->fTheta->GetRandom();
			  				  			    		 
	   	   //momentum components
				px = TMath::Sin(phi)*TMath::Sin(theta); 
				pz = TMath::Cos(phi)*TMath::Sin(theta);
				py = -TMath::Cos(theta);
				
				// start position, area 1120m^2
				x = fRandomEngine->Uniform(-xdist/2,xdist/2);
				z = fRandomEngine->Uniform(z0 - zdist/2, z0 + zdist/2);
				
				// claim for flight close to the actual detector
				if((abs(x-(y+yTop)*px/py) < xTop && abs(z-z0-(y+yTop)*pz/py) < zTop) || (abs(x-(y-yTop)*px/py) < xTop && abs(z-z0-(y-yTop)*pz/py) <  zTop)|| abs(y-(x+xTop)*py/px)<yTop && abs(z-z0-(x+xTop)*pz/px)<zTop || abs(y-(x-xTop)*py/px)<yTop && abs(z-z0-(x-xTop)*pz/px)<zTop){
					
					// muon momentum
					double P;
					//if (!high) {P = fRandomEngine->NEWstest(theta);}
					//else {P = fRandomEngine->fSpectrumH->GetRandom();}
					// high
					P = fRandomEngine->fSpectrumH->GetRandom();
					w = weight1High/weight3/kmax;
					StartP->Fill(P,w);
					StartPHigh->Fill(P,w);
					StartPTheta->Fill(P,theta,w);
					// low
					P = fRandomEngine->NEWstest(theta);
					w = weight1Low/weight3/kmax;
					StartP->Fill(P,w);
					StartPLow->Fill(P,w);
					StartPTheta->Fill(P,theta,w);
					
					
					px = px*P;
					py = py*P;
					pz = pz*P;
					
					//muon or anti-muon
					hit = 1; nInside++; 
					// StartP->Fill(P,w);
					
					w = weight1Low/weight3/kmax + weight1High/weight3/kmax;
					
					StartTheta->Fill(theta,w); // kein Weight!
					StartPhi->Fill(phi,w);	// kein Weight!	
					StartXZ->Fill(x,z,w); // kein Weight!	
					StartPTheta->Fill(P,theta,w);	
			   }
			   nTry++;
				weighttest += w;
				MCTheta->Fill(theta,w); // kein Weight!
				MCPhi->Fill(phi,w);
				MCXZ->Fill(x,z,w);
				nTest++;
			}while(!hit);
			nEvent++;
		}
		MCnTry->Fill(1.0*nTry/EVENTS);
	}
	clock0->Stop();
	
	delete fRandomEngine;
	cout<<nEvent<<" events have been generated."<<endl;
	cout<<"There is a total of "<<nInside<<"/"<<nTest<<" muons that passed close enough to the detector."<<endl;
	cout<<"Including the given weight this corresponds to ";
	cout<<kmax*weighttest/xdist/zdist*10000/123.3044<<" spills (1 spill = "<<xdist*zdist*123.3044/10000;
	cout<<" real cosmic muons = "<<EVENTS<<" simulated events)."<<endl;
   
   cout<<weighttest<<endl;
   clock0->Print();
   
   Double_t meanflux = 0;
   Int_t binsum = 0;
   for (Int_t ix = 2; ix<29;ix++){
	   for (Int_t iz = 2; iz<89;iz++){
		 	binsum++;
		   meanflux += MCXZ->GetBinContent(ix,iz);
		}
	}
	cout<< "meanflux: "<<meanflux/binsum<<"  "<< meanflux<<endl<<endl;
   printf("MCnTry: %.9f +- %.9f",MCnTry->GetMean(),MCnTry->GetMeanError());
   cout<<endl<<endl;
     
    TCanvas *c1 = new TCanvas("c1","c1",400,400);
	 c1->Divide(1,1);
	 c1->cd(1);
	 MCnTry->DrawCopy();
	
	 TCanvas *c4 = new TCanvas("c4","c4",400,400);
	 c4->Divide(1,1);
	 c4->cd(1);
	 StartPTheta->DrawCopy("SURF2");
	 gPad->SetLogx();
	
	 //TCanvas *c2 = new TCanvas("c2","c2",400,400);
	 //c2->Divide(1,1);
	 //c2->cd(1);
	 //gPad->SetLogy();
	 //wei->DrawCopy();
	
    TCanvas *c3 = new TCanvas("c3","c3",1600,800);
	 c3->Divide(4,2);
	 c3->cd(1);
	 StartXZ->DrawCopy("COLZ");
	 c3->cd(2);
	 //MCP->SetLineColor(kGreen);
	// MCP->DrawCopy();
	 //StartP->DrawCopy();
	 //TF1 *fs = new TF1("fs",NEWs,1,100,2);
	 //fs->FixParameter(0, 0);
	 //fs->FixParameter(1, 500);
	 //StartP->Add(fs,-1);
	 StartP->DrawCopy();
	 //StartP->Fit(fs,"I");
	 
	 
	// 
	 //fs->DrawCopy("SAME");
	 
	 //gPad->SetLogy();
	 gPad->SetLogx();
	 c3->cd(3);
	 MCTheta->SetLineColor(kGreen);
	 MCTheta->DrawCopy();
	 StartTheta->DrawCopy("SAME");
	 //TF1 *f1 = new TF1("f1","[0]*cos(x)*cos(x)",1.57,3.14);
	 //StartTheta->Fit(f1,"","",1.57,3.14);	
	 gPad->SetLogy(0);
	 gPad->SetLogx(0);
	 c3->cd(4);
	 MCPhi->SetLineColor(kGreen);
	 MCPhi->DrawCopy();
	 StartPhi->DrawCopy("SAME");
	//TF1 *f1 = new TF1("f1","[0]*cos(x)*cos(x)",1.57,3.14);
	//StartTheta->Fit(f1,"","",1.57,3.14);	
	 gPad->SetLogy(0);
	 gPad->SetLogx(0);
	 c3->cd(5);
	 MCXZ->DrawCopy("COLZ");
	 c3->cd(6);
	 //MCP->Divide(StartP);
	// MCP->DrawCopy();
	 gPad->SetLogy(0);
	 gPad->SetLogx(0);
	 c3->cd(7);
	 //MCTheta->Divide(StartTheta);
	 MCTheta->DrawCopy();
	 gPad->SetLogy();
	 gPad->SetLogx(0);
	 c3->cd(8);
	 //MCPhi->Divide(StartPhi);
	 MCPhi->DrawCopy();
	 gPad->SetLogy(0);
	 gPad->SetLogx(0);
	 c3->Update();
	 c3->SaveAs("Start.png");
	 
	 
	 
	 
	 StartXZ->Write();
	 StartTheta->Write();
	 StartPhi->Write();
	 StartP->Write();
	 StartPLow->Write();
	 StartPHigh->Write();
	
    StartPTheta->Write();
		
	 MCXZ->Write();
	 MCTheta->Write();
	 MCPhi->Write();
	
	 MCnTry->Write();
	 fout ->Close();
	 
	 
  
}
예제 #5
0
void scan2() {

    /*  TFile f1("hist.root");
      TFile f2("SysTot.root");

      TH1D *datahist = (TH1D*)f1.Get("datahist");
      TH1D *fithist = (TH1D*)f1.Get("fithist");

      TH1D *totlow = (TH1D*)f2.Get("totlow");
      TH1D *tothigh = (TH1D*)f2.Get("tothigh");
    */

    TF1 *fun1 = new TF1("fun",fun,0,1000,3);

    TFile f("Output.root");
    TH1F *datahist = dynamic_cast<TH1F*> (f.Get("InvMass"));
    TH1F *fithist = dynamic_cast<TH1F*> (f.Get("hist_err"));
    TH1F *tothigh = dynamic_cast<TH1F*> (f.Get("SystPlus"));
    TH1F *totlow = dynamic_cast<TH1F*> (f.Get("SystMinus"));
    new TCanvas();
    datahist->DrawCopy();
    fithist->DrawCopy("same");
    gPad->SetEditable(0);

    /*	if (datahist->IsZombie()) { std::cout << "Err! datahist not found " << std::endl; return; }
    	if (fithist->IsZombie()) { std::cout << "Err! err_hist not found " << std::endl; return; }
    	if (tothigh->IsZombie()) { std::cout << "Err! syst_plus hist not found " << std::endl; return; }
    	if (totlow->IsZombie()) { std::cout << "Err! syst_minus hist not found " << std::endl; return; }
    */

    TH1D *p = new TH1D("p","Probability",100,150,900);

    for (int i = 1; i<=fithist->GetNbinsX(); i++)
    {
        double mass = fithist->GetBinCenter(i);

        if (mass>440 && mass<450)
        {
            double sigma = sqrt(2.0)*sqrt(pow(0.135*sqrt(mass/2.0),2)+
                                          pow(0.02*(mass/2.0),2));
            cout<< " ===================== mass +/- sigma = " << mass<<"+/-"<<sigma<<endl;
            int bin1 = fithist->FindBin(mass-sigma/2);
            int bin2 = fithist->FindBin(mass+sigma/2);
            cout<<mass<<" "<<bin1<<" "<<bin2<<endl;
            double data = 0;
            double bg = 0;
            double err = 0;

            for (int j = bin1; j<=bin2; j++)
            {
                data+=datahist->GetBinContent(j);
                bg+=fithist->GetBinContent(j);
                double err1 = -totlow->GetBinContent(j);
                double err2 = tothigh->GetBinContent(j);
                err+=TMath::Max(err1,err2)*bg; //why multiply by bg???
            }
            cout << "Total Data/Bg+/-err in mass window[" << mass << "] = "<< data <<"/ "<< bg << "+/-" << err <<endl;
            double prob = 0;
            fun1->SetParameter(0,bg);
            fun1->SetParameter(1,err);

            for (int j = int(data+0.001); j<100; j++) {
                fun1->SetParameter(2,j);
                //fun1->Print();
                //cout << "Evaluating Intrgral for j = " << j << " from x0= " << TMath::Max(0.0,bg-10*err) << " to x1 = " << bg+10*err << endl;
                double val = fun1->Integral(TMath::Max(0.0,bg-10*err),bg+10*err);
                //double val = fun1->Integral(TMath::Max(0.0,bg-2*err),bg+2*err);
                /*for (int z=TMath::Max(0.0,bg-2*err); z < bg+2*err; ++z)
                {
                	if (c<4)
                	{
                	std::cout << "func at [" << z << "]=" << 	fun1->Eval(z) << std::endl;
                	}
                }
                */
                prob += val;
            }
            cout<< "Prob for mass[" << mass<<"]="<< prob <<endl;
            p->SetBinContent(p->FindBin(mass),prob);
        }
    }
    /*
    delete gRandom;
    gRandom = (TRandom*) new TRandom3;
    gRandom->SetSeed(3);

    TH1D *minp = new TH1D("minp","Minimum Probability of Each PseudoExpt",100,0,0.2);

    //int nexp = 50000;
    int nexp = 10;

    TH1D *htemp = (TH1D*)datahist->Clone("htemp");

    for (int iexp = 0; iexp<nexp; iexp++){
      //if (iexp%10==0) cout<<iexp<<endl;
      //generate pseudo-experiments
      htemp->Reset();
      for (int i = 1; i<=htemp->GetNbinsX(); i++){
        double mass = htemp->GetBinCenter(i);
        if (mass>150&&mass<650){
    double bg = fithist->GetBinContent(i);
    double err1 = -totlow->GetBinContent(i);
    double err2 = tothigh->GetBinContent(i);
    double err = TMath::Max(err1,err2)*bg;
    double mean = gRandom->Gaus(bg,err);
    if (mean<0) mean = 0;
    htemp->SetBinContent(i,gRandom->Poisson(mean));
        }
      }
      double minprob = 2.;
      for (int i = 1; i<=fithist->GetNbinsX(); i++){
        double mass = fithist->GetBinCenter(i);
        if (mass>150&&mass<650){
    double sigma = sqrt(2.0)*sqrt(pow(0.135*sqrt(mass/2.0),2)+
    			      pow(0.02*(mass/2.0),2));
    //cout<<mass<<" "<<sigma<<endl;
    int bin1 = fithist->FindBin(mass-sigma/2);
    int bin2 = fithist->FindBin(mass+sigma/2);
    //cout<<mass<<" "<<bin1<<" "<<bin2<<endl;
    double data = 0;
    double bg = 0;
    double err = 0;
    for (int j = bin1; j<=bin2; j++){
      data+=htemp->GetBinContent(j);
      bg+=fithist->GetBinContent(j);
      double err1 = -totlow->GetBinContent(j);
      double err2 = tothigh->GetBinContent(j);
      err+=TMath::Max(err1,err2)*bg;
    }
    //cout<<mass<<" "<<data<<" "<<bg<<" "<<err<<endl;
    double prob = 0;
    fun1->SetParameter(0,bg);
    fun1->SetParameter(1,err);
    for (int j = int(data+0.001); j<100; j++){
      fun1->SetParameter(2,j);
      prob += fun1->Integral(TMath::Max(0.0,bg-10*err),bg+10*err);
    }
    if (prob<minprob) minprob=prob;
        }
      }
      minp->Fill(minprob);
    }
    */
    TCanvas *c1 = new TCanvas("c1","c1");
    TH2D *fr = new TH2D("fr","",100,150,900,100,1e-5,2);
    fr->SetStats(0);
    fr->SetXTitle("M(#gamma,lead jet)(GeV)");
    fr->SetYTitle("Prob of fluctuation #geq N_{obs}");
    fr->GetXaxis()->CenterTitle();
    fr->GetYaxis()->CenterTitle();
    fr->DrawCopy();
    p->SetLineWidth(2);
    p->DrawCopy("same");
    double minp=0;
    double mgg=0;
    double minc = 10;
    for (int i = 1; i<=p->GetNbinsX(); i++) {
        double bin = p->GetBinCenter(i);
        double binc = p->GetBinContent(i);
        if (binc<minc) {
            minp = binc;
            mgg = bin;
            minc = binc;
        }
    }
    cout<<mgg<<" "<<minp<<endl;
    gPad->SetLogy();
    double p1s = 0.00458319;
    double m1s = 0.0435982;
    double s3s = 0.000100319;
    TLine *l1 = new TLine(150,p1s,900,p1s);
    TLine *l2 = new TLine(150,m1s,900,m1s);
    TLine *l3 = new TLine(150,s3s,900,s3s);
    l1->SetLineColor(4);
    l2->SetLineColor(4);
    l3->SetLineColor(2);
    l1->SetLineWidth(2);
    l2->SetLineWidth(2);
    l3->SetLineWidth(2);
    l1->Draw();
    l2->Draw();
    l3->Draw();
    TLatex *t1 = new TLatex(250,m1s/4,"Expected Range for Min. Obs. Prob.");
    t1->SetTextColor(4);
    t1->SetTextSize(0.05);
    t1->Draw();
    TLatex *t2 = new TLatex(350,s3s*1.5,"3 #sigma evidence level");
    t2->SetTextColor(2);
    t2->SetTextSize(0.05);
    t2->Draw();

    TLatex *t3 = new TLatex(0.3,0.93,"CDF Run II Preliminary, 2.0 fb^{-1}");
    t3->SetNDC(true);
    t3->SetTextSize(0.06);
    t3->Draw();

//
//  TCanvas *c2 = new TCanvas("c2","c2");
//  minp->DrawCopy();
    //cout<<minp->GetMean()<<endl;
}
예제 #6
0
int genbod_diff(const char* filename1, const char* filename2, bool ifSave = false)
{
  TFile* f1 = new TFile(filename1,"READ");
  TFile* f2 = new TFile(filename2,"READ");

  TH2D* numF1 = ((TH2D*) f1->Get("cnumepNonIdEP"));
  TH2D* numF2 = ((TH2D*) f2->Get("cnumepNonIdEP"));
  TH2D* denF1 = ((TH2D*) f1->Get("cdenepNonIdEP"));
  TH2D* denF2 = ((TH2D*) f2->Get("cdenepNonIdEP"));
  TH2D* numB1 = ((TH2D*) f1->Get("cnumepNonIdEPTrue"));
  TH2D* numB2 = ((TH2D*) f2->Get("cnumepNonIdEPTrue"));
  TH2D* denB1 = ((TH2D*) numF1->Clone());
  TH2D* denB2 = ((TH2D*) numF2->Clone());
  TH2D* numC1 = ((TH2D*) numB1->Clone());
  TH2D* numC2 = ((TH2D*) numB2->Clone());
  TH2D* denC1 = ((TH2D*) f1->Get("cdenepNonIdEPTrue"));
  TH2D* denC2 = ((TH2D*) f2->Get("cdenepNonIdEPTrue"));

  double eta = 1.1;
  gStyle->SetOptStat(111);
  //TCanvas* canv = new TCanvas("canv", "GENBOD results", 10,10,800,600);
   TCanvas* canv = new TCanvas("canv", "GENBOD results", 10,10,1600,1200);
  canv->Divide(3,3);
  //TCanvas* canvND = new TCanvas("canvND", "liczniki i mianowniki ", 10,10,800,600);
  TCanvas* canvND = new TCanvas("canvND", "liczniki i mianowniki ", 10,10,1600,1200);
  canvND->Divide(2,2);

  //////   Pure Corr fun
  TH2D* numdiff = (TH2D*)numF1->Clone();
  numdiff->Divide(numF2);
  canvND->cd(1); numdiff->DrawCopy("colz");
  TH2D* dendiff = (TH2D*)denF1->Clone();
  dendiff->Divide(denF2);
  canvND->cd(2); dendiff->DrawCopy("colz");
  double sF1 = numF1->GetEntries()/denF1->GetEntries();
  numF1->Divide(denF1);
  numF1->Scale(1./sF1);
  numF1->GetYaxis()->SetRangeUser(-eta,eta);
  double sF2 = numF2->GetEntries()/denF2->GetEntries();
  numF2->Divide(denF2);
  numF2->Scale(1./sF2);
  numF2->GetYaxis()->SetRangeUser(-eta,eta);
  canv->cd(1);
  TH2D* corrF1 = (TH2D*) numF1->Clone();
  corrF1->Draw("surf1");
  DrawNicely(corrF1, 0,0, filename1);
  canv->cd(2);
  TH2D* corrF2 = (TH2D*) numF2->Clone();
  corrF2->Draw("surf1");
  DrawNicely(corrF2, 0,0, filename2);
  canv->cd(3);
  numF1->Divide(numF2);
  DrawNicely(numF1, 0,0, "Femtoscopic component");
  numF1->Draw("colz");
  
  ////// Pure Bkg
  TH2D* numdiffTrue = (TH2D*)numB1->Clone();
  numdiffTrue->Divide(numB2);
  canvND->cd(3); numdiffTrue->DrawCopy("colz");
  double sB1 = numB1->GetEntries()/denB1->GetEntries();
  numB1->Divide(denB1);
  numB1->Scale(1./sB1);
  numB1->GetYaxis()->SetRangeUser(-eta,eta);
  double sB2 = numB2->GetEntries()/denB2->GetEntries();
  numB2->Divide(denB2);
  numB2->Scale(1./sB2);
  numB2->GetYaxis()->SetRangeUser(-eta,eta);
  canv->cd(4);
  TH2D* corrB1 = (TH2D*) numB1->Clone();
  corrB1->Draw("surf1");
  DrawNicely(corrB1, 0,0, filename1);
  canv->cd(5);
  TH2D* corrB2 = (TH2D*) numB2->Clone();
  corrB2->Draw("surf1");
  DrawNicely(corrB2, 0,0, filename2);
  canv->cd(6);
  numB1->Divide(numB2);
  DrawNicely(numB1, 0,0, "Background component");
  numB1->DrawCopy("colz");
  
  //////   Norm Corr fun
  TH2D* dendiffTrue = (TH2D*)denC1->Clone();
  dendiffTrue->Divide(denC2);
  canvND->cd(4); dendiffTrue->DrawCopy("colz");
  double sC1 = numC1->GetEntries()/denC1->GetEntries();
  numC1->Divide(denC1);
  numC1->Scale(1./sC1);
  numC1->GetYaxis()->SetRangeUser(-eta,eta);
  double sC2 = numC2->GetEntries()/denC2->GetEntries();
  numC2->Divide(denC2);
  numC2->Scale(1./sC2);
  numC2->GetYaxis()->SetRangeUser(-eta,eta);
  canv->cd(7);
  TH2D* corrC1 = (TH2D*) numC1->Clone();
  corrC1->Draw("surf1");
  DrawNicely(corrC1, 0,0, filename1);
  canv->cd(8);
  TH2D* corrC2 = (TH2D*) numC2->Clone();
  corrC2->Draw("surf1");
  DrawNicely(corrC2, 0,0, filename2);
  canv->cd(9);
  numC1->Divide(numC2);
  DrawNicely(numC1, 0,0, "Correlation function");
  numC1->DrawCopy("colz");
  
  //save
  if (ifSave)
  {
    canv->Print(Form("diff_%s_%s_global.png",filename1,filename2));
    canvND->Print(Form("diff_%s_%s_global_NumDen.png",filename1,filename2));
  }
}
예제 #7
0
// ----------------------------------------------------------------------
void moduleSummary(const char *dirName = "", const char *module_type) 
{

  printf("\nmoduleSummary> Starting ...\n");

  nChips = 16;
  startChip = 0;
	
  if ( !strcmp(module_type,"a") ) {
    
    nChips = 8; 
    startChip = 0; 
  }
  
  if ( !strcmp(module_type,"b") ) {
    
    nChips = 8; 
    startChip = 8; 
  }

  sprintf(fname, "%s/%s", dirName, fileName);
  inputFile = fopen(fname, "r");
  if (!inputFile) { 

    printf("\nmoduleSummary> ----> COULD NOT FIND %s IN DIRECTORY %s\n", fileName, dirName);
    printf("moduleSummary> ----> Aborting execution of moduleSummaryPage.C ... \n\n", fileName, dirName);   
    break; 
  }

  
  sprintf(fname, "%s/%s", dirName, adFileName);
  inputFile = fopen(fname, "r");
  if (!inputFile) {
    
    sprintf(adFileName,"%s", fileName); 
  }
  else {
    
    printf("moduleSummary> ----> found separate address decoding file: %s\n", adFileName); 
    fclose (inputFile); 
  }
  
  sprintf(fname, "%s/../../macros/criteria.dat", dirName);
  if ( !readCriteria(fname) ) {  
    
    printf("\nmoduleSummary> ----> COULD NOT READ GRADING CRITERIA !!!\n");
    printf("moduleSummary> ----> Aborting execution of moduleSummaryPage.C ... \n\n", fileName, dirName);  
    break;
  }

  TFile *f = new TFile(Form("%s/%s", dirName, fileName));

  gROOT->SetStyle("Plain");
  
  gStyle->SetPalette(1);
  gStyle->SetOptStat(0);
  gStyle->SetTitle(0);

  gStyle->SetStatFont(132);
  gStyle->SetTextFont(132);
  gStyle->SetLabelFont(132, "X");
  gStyle->SetLabelFont(132, "Y");
  gStyle->SetLabelSize(0.08, "X");
  gStyle->SetLabelSize(0.08, "Y");
  gStyle->SetTitleSize(0.08, "X");
  gStyle->SetTitleSize(0.08, "Y");
  gStyle->SetNdivisions(10, "X");
  gStyle->SetNdivisions(8, "Y");
  gStyle->SetTitleFont(132);
    
  gROOT->ForceStyle();
  
  tl = new TLatex;
  tl->SetNDC(kTRUE);
  tl->SetTextSize(0.1);
  
  ts = new TLatex;
  ts->SetNDC(kTRUE);
  ts->SetTextSize(0.09);

  line = new TLine;
  line->SetLineColor(kRed);
  line->SetLineStyle(kDashed);

  box = new TBox;
  box->SetFillColor(3);
  box->SetFillStyle(3004);

  c1 = new TCanvas("c1", "", 900, 700);
  c1->Clear();
  c1->Divide(1,4);
    
  int EColor[6]        = { 4, 8, 6, 1 };  
  int EMarkerStyle[10] = { 4, 25, 26, 23, 21, 27, 28, 20, 30, 29 };

  TH2D *mThreshold = new TH2D("mThreshold", "", 416, 0., 416., 160, 0., 160.);
  TH2D *mBumps     = new TH2D("mBumps",     "", 416, 0., 416., 160, 0., 160.);
  TH2D *mAddr      = new TH2D("mAddr",      "", 416, 0., 416., 160, 0., 160.);  

  double mThresholdmin(0.), mThresholdmax(255.);


  const int nfit = 4;  
  TString fitNames[] = {TString("Noise"), TString("Vcal Thr. Width"), TString("Rel. Gain Width"), TString("Pedestal Spread")};

  float limitB[] = { noiseB, trimmingB, gainB, pedestalB };   // limit for grading
  float limitC[] = { noiseC, trimmingC, gainC, pedestalC };   // limit for grading
  float max[]   = { noiseB + 100., trimmingB + 100., gainB + 0.05, pedestalB + 1000. };    // scaling of histogram

  TH1D *fit[nfit];
  TH1D *fitEntries[nfit];

  for(int ifit = 0; ifit < nfit; ++ifit) {

    fit[ifit] = new TH1D(Form("%s", fitNames[ifit].Data()),"", nChips, float(startChip), float(startChip+nChips));
    fitEntries[ifit] = new TH1D(Form("n%s", fitNames[ifit].Data()),"", nChips, float(startChip), float(startChip+nChips));

    fit[ifit]->SetLineColor(EColor[ifit]);
    fit[ifit]->SetMarkerColor(EColor[ifit]);
    fit[ifit]->SetMarkerStyle(EMarkerStyle[ifit]);
    fit[ifit]->SetMarkerSize(0.5);
  }
 
  for (int i = startChip; i < startChip+nChips; i++) { addVcalThreshold(dirName, i, mThreshold); }
  for (int i = startChip; i < startChip+nChips; i++) { addChip("vcals_xtalk", i, mBumps); }

  TFile *f1 = new TFile(Form("%s/%s", dirName, adFileName));
  for (int i = startChip; i < startChip+nChips; i++) { addChip("AddressDecoding", i, mAddr);}

  if ( nChips < 16 && startChip == 0 ) { 
    for (int i = 8; i < nChips+8; i++) { removeChip(i, mThreshold, -99); }
    for (int i = 8; i < nChips+8; i++) { removeChip(i, mBumps, -99); }
    for (int i = 8; i < nChips+8; i++) { removeChip(i, mAddr, -99); }
  }

  if ( nChips < 16 && startChip == 8 ) { 
    for (int i = 0; i < nChips; i++) { removeChip(i, mThreshold, -99); }
    for (int i = 0; i < nChips; i++) { removeChip(i, mBumps, -99); }
    for (int i = 0; i < nChips; i++) { removeChip(i, mAddr, -99); }
  }

  TString noslash(dirName);
  noslash.ReplaceAll("/", "");
  noslash.ReplaceAll("..", "");
  
  c1->cd(1);

  if ( mThreshold->GetMaximum() < mThresholdmax ) { 
    mThresholdmax = mThreshold->GetMaximum();
  }
  if ( mThreshold->GetMinimum() > mThresholdmin ) {
    mThresholdmin = mThreshold->GetMinimum();
  }
  mThreshold->GetZaxis()->SetRangeUser(mThresholdmin,mThresholdmax);
  mThreshold->DrawCopy("colz");
  tl->DrawLatex(0.1, 0.92, "Vcal threshold");
  tl->DrawLatex(0.75, 0.92, Form("%s",noslash.Data()));

  if ( nChips < 16 && startChip == 0 ) { 
   
    box->SetFillColor(29);
    box->DrawBox( 0, 0,  416,  80);
  }

  if ( nChips < 16  && startChip == 8 ) { 
   
    box->SetFillColor(29);
    box->DrawBox( 0, 80,  416,  160);
  }



  c1->cd(2);
  mBumps->SetMaximum(2.);
  mBumps->SetMinimum(-2.);  
  mBumps->DrawCopy("colz");
  tl->DrawLatex(0.1, 0.92, "Bump bonding map");

  if ( nChips < 16 && startChip == 0 ) { 
   
    box->SetFillColor(29);
    box->DrawBox( 0, 0,  416,  80);
  }

  if ( nChips < 16 && startChip == 8 ) { 
   
    box->SetFillColor(29);
    box->DrawBox( 0, 80,  416,  160);
  }
  
  c1_3->Divide(3,1);
  c1_3->cd(1);
  gPad->SetBottomMargin(0.2);
  gPad->SetLogy(1);
  gPad->SetLeftMargin(0.20);
  gPad->SetRightMargin(0.01);
  
  float V, A;
  float x_V[250], y_A[250];
  int i(0); 
  float iv100(0.);
  float iv150(0.);
  float iv150_17(0.);
  float iv100_17(0.);
  float variation(0.);
  float variation_17(0.);
  
  FILE *ivFile, *sumWrite, *sumRead, *gradWrite; 
    
  sprintf(fname, "%s/iv.dat", dirName);
  ivFile = fopen(fname, "r");
  
  if (!ivFile)
  {
    printf("moduleSummary> !!!!!!!!!  ----> Could not open file %s to read data\n", fname);
  }
  
  else {
  
    fclose(ivFile);
    ifstream is(fname);
    
    char  buffer[200];
    
    while (is.getline(buffer, 200, '\n')) {
      
      // check that line starts with a number
      if (buffer[0] != '1' && buffer[0] != '2' && buffer[0] != '3' && buffer[0] != '4' && 
	  buffer[0] != '5' && buffer[0] != '6' && buffer[0] != '7' && buffer[0] != '8' && buffer[0] != '9'  )  {continue;} 
      
      sscanf(buffer, "%e %e", &V, &A);
      
      x_V[i] = V;
      y_A[i] = 1e6*A;
      
      if ( i > 0 ) {
	
        // check that voltage is increasing & find current at 150 V 
        if ( x_V[i] < x_V[i-1] ) { continue; }
	if ( x_V[i] >= 100. && x_V[i-1] <= 100. ) { iv100 = y_A[i-1] + (100. - x_V[i-1])*(y_A[i] - y_A[i-1])/(x_V[i] - x_V[i-1]); }
	if ( x_V[i] >= 150. && x_V[i-1] <= 150. ) { iv150 = y_A[i-1] + (150. - x_V[i-1])*(y_A[i] - y_A[i-1])/(x_V[i] - x_V[i-1]); }
	
      }
      
      i++;
      
    }
 
 
    if ( iv100 != 0. ) { variation = iv150/iv100; }
    else               { variation = 0; }

    if ( i > 0 ) {
    
      TGraph *g1 = new TGraph(i,x_V,y_A);

      g1->Draw("aC");
      g1->SetTitle("");
      g1->SetLineColor(4);
      g1->SetLineWidth(2);
    
      g1->GetXaxis()->SetTitle("Voltage [V]");
      g1->GetYaxis()->SetTitle("Current [#muA]");
      g1->GetYaxis()->SetDecimals();
      g1->GetYaxis()->SetTitleOffset(1.2);
      g1->GetYaxis()->CenterTitle();
  
      tl->DrawLatex(0.2, 0.92, "I-V-Curve");
      ts->DrawLatex(0.25, 0.78, Form("I(150 V) = %.2f #muA", iv150));
      ts->DrawLatex(0.25, 0.65, Form("I_{150}/I_{100} =  %.2f ", variation));

    }   
  }
    
  char mod[20] = noslash.Data(), waf[20] = "",  test[20] = "",tmon[20], trim[20], ph[20], cycl[20];
  int tday;
  int dp(0), dm(0), db(0), dt(0), da(0);
  int root(0), a(0), b(0), c(0); 
  int badRocs[3] = {0, 0, 0};
  char iv;
  float voltage, current; 
  float temp, tempSigma, sollTemp;
  float cyclMean, cyclSigma;
  char  string[1000];
  
  c1_3->cd(2);
  
  sprintf(fname, "%s/summaryTest.txt", dirName);
  sumRead = fopen(fname, "r");

  if (!sumRead)
  {
    printf("\nmoduleSummary> !!!!!!!!!  ----> File %s does not exist yet...\n", fname);
    printf("moduleSummary> !!!!!!!!!  ----> Module summary not complete!\n\n");
  }
  else
  {
    fgets(string, 200, sumRead);
    //   fscanf(sumRead, "%s %s", string, mod);
    fscanf(sumRead, "%s %s %s %s", string, string, waf, test);
    fscanf(sumRead, "%s %i %i %i %i %i", string, &dp, &dm, &db, &dt, &da);
    fscanf(sumRead, "%s %s %s %s %s %i %i %i", string, string, string, string, string, &a, &b, &c);
    badRocs[0]=a;  badRocs[1]=b;  badRocs[2]=c;
    fscanf(sumRead, "%s %s %i", string, string, &root);
    fscanf(sumRead, "%s %s %s %s %s %i %s %s", string, string, string, string, tmon, &tday, string, string);

    fgets(string, 200, sumRead);
    fscanf(sumRead, "%s %s", string, trim);
    fgets(string, 200, sumRead); 
    fscanf(sumRead, "%s %s", string, ph);
    fgets(string, 200, sumRead);
    
    fscanf(sumRead, "%s %f %f %s %f", string, &temp, &tempSigma, string, &sollTemp); 

    fscanf(sumRead, "%s %s %s %f %f", string, string, cycl, &cyclMean, &cyclSigma);

    fclose(sumRead);
    
    tl->SetTextSize(0.09);
    tl->SetTextFont(22);
    double y = 0.92;
    tl->DrawLatex(0.01, y, Form("Test Summary of %s     %s", waf, test));
    tl->SetTextFont(132); 
    tl->SetTextSize(0.09);

    y -= 0.16;
    tl->DrawLatex(0.01, y, "ROCs > 1% defects: ");
    tl->DrawLatex(0.5, y, Form("%i", badRocs[0]));
    
    y -= 0.12;
    tl->DrawLatex(0.01, y, Form("Dead Pixel: "));
    tl->DrawLatex(0.5, y, Form("%i", dp));

    y -= 0.11;
    tl->DrawLatex(0.01, y, "Mask Defects: ");
    tl->DrawLatex(0.5, y, Form("%i", dm));

    y -= 0.11;
    tl->DrawLatex(0.01, y, "Dead Bumps: ");
    tl->DrawLatex(0.5, y, Form("%i", db));

    y -= 0.11;
    tl->DrawLatex(0.01, y, "Dead Trimbits: ");
    tl->DrawLatex(0.5, y, Form("%i", dt));

    y -= 0.11;
    tl->DrawLatex(0.01, y, "Address Probl: ");
    tl->DrawLatex(0.5, y, Form("%i", da));

    y = 0.76;
    tl->DrawLatex(0.72, y, Form("Tested on:"));
    y -= 0.11;
    tl->DrawLatex(0.72, y, "Temp. [^{o}C]:  ");
    y -= 0.11;
    tl->DrawLatex(0.72, y, "Trim / phCal: ");
    y -= 0.11;
    tl->DrawLatex(0.72, y, "Therm. cycl.: ");
    y -= 0.11;
    tl->DrawLatex(0.72, y, "TBM1: ");
    y -= 0.11;
    tl->DrawLatex(0.72, y, "TBM2: ");

    c1_3->cd(3);
    y = 0.76;
    tl->DrawLatex(0.01, y, Form("%s %i", tmon, tday));
    
    y -= 0.11;
    tl->DrawLatex(0.01, y, Form("%.1f +- %.1f", temp, tempSigma));
              
    y -= 0.11;
    tl->DrawLatex(0.01, y, Form("%s / %s", trim, ph));

    y -= 0.11;
    tl->DrawLatex(0.01, y, Form("%s", cycl));

  }

  int result;
  int tbm1(1), tbm2(1);
  TParameter<int>* par;
  
  y -= 0.11;
  par = (TParameter<int>*)f->Get("TBM1");
  if (par)
  {
  	tbm1 = par->GetVal();
  	if (tbm1 == 0) tl->DrawLatex(0.01, y, "ok");   
  	else tl->DrawLatex(0.01, y, Form("Err%i", tbm1));   
  }

  y -= 0.11;
  par = (TParameter<int>*)f->Get("TBM2");
  if (par)
  {
	tbm2 = par->GetVal();
	if (tbm2 == 0) tl->DrawLatex(0.01, y, "ok");   
	else tl->DrawLatex(0.01, y, Form("Err%i", tbm2));   
  }


  // Convert current to currents at room temperature
  double Tk = 273.15;
  double egap = 1.12;
  double kB = 8.617343E-5;
  double tTest;
  // tTest = temp;  // --> averaged temperature
  tTest = sollTemp;
  
  double expnt  = egap*(1/(Tk+tTest) - 1/(Tk+17))/(2*kB);
  double fctr   = (Tk+17)*(Tk+17)/((Tk+tTest)*(Tk+tTest));
  
  iv150_17 = iv150*fctr*TMath::Exp(expnt);
  iv100_17 = iv100*fctr*TMath::Exp(expnt);
  if ( iv100_17 != 0 ) variation_17 = iv150_17/iv100_17;
    
  printf("\nmoduleSummary> converted I(150 V, %.0f C)    = %.4f       to  I(150 V, 17 C)    = %.4f \n", tTest, iv150, iv150_17);
  printf("moduleSummary> converted I(100 V, %.0f C)    = %.4f       to  I(100 V, 17 C)    = %.4f \n\n", tTest, iv100, iv100_17);
  
  if ( iv150_17 != 0 ) {
    c1_3->cd(3);
    y = 0.32;
    tl->DrawLatex(0.25, y, "I(150 V) [T = 17 ^{o}C]");
    tl->DrawLatex(0.72, y, Form("%.2f #muA", iv150_17));
    c1_3->cd(2);
    
  }

  if ( iv100_17 != 0 ) {
    c1_3->cd(3);
    y = 0.21;
    tl->DrawLatex(0.25, y, "I_{150}/I_{100}   [T = 17 ^{o}C]");
    tl->DrawLatex(0.72, y, Form("%.2f", variation_17));
    c1_3->cd(2);
  }

  sprintf(fname, "%s/summaryTest.txt", dirName);
  sumWrite = fopen(fname, "a");
  fputs(Form("TBM1 %i\n", tbm1), sumWrite);
  fputs(Form("TBM2 %i\n", tbm2), sumWrite);
  fputs(Form("I 150 %f \n", iv150_17), sumWrite);
  fputs(Form("I150/I100 %f \n", variation_17), sumWrite);
  fputs(Form("iv datapoints %i \n", i), sumWrite);

//   c1->cd(4);
//   mAddr->DrawCopy("colz");
//   mAddr->SetMaximum(1.);
//   mAddr->SetMinimum(0.);
//   tl->DrawLatex(0.1, 0.92, "Address decoding map");



  c1_4->Divide(4,1);
  qualification(dirName, fit, fitEntries);
  

  for (int i = 0; i < 4; i++) {

  // makePlot(TH1 *h, const char *title, int pad, double Ymin, double Ymax, double Ylimit)
    makePlot(fit[i], fitNames[i].Data(), i+1, 0, max[i], limitB[i], limitC[i]); 
  
  }

  int grad(0);

  FILE *missingData; 
  sprintf(fname, "%s/comment_3.txt", dirName);
  missingData = fopen(fname, "r");

  if ( missingData ) {

    printf("\nmoduleSummary> !!!!!!!!!  ----> Found file for missing data: comment_3.txt => GRADE C!\n\n");
    grad = 3;
    fclose(missingData);

  } else {
  
    grad = grading(badRocs, iv150_17, variation_17, fit, fitEntries, limitB, limitC, test);
  }
  
  c1_3->cd(3);    
  tl->SetTextSize(0.09);
  tl->SetTextFont(22);
 
  if (grad == 1) {  tl->DrawLatex(0.6, 0.92, "GRADE:  A");  fputs("Grade A\n", sumWrite); }
  if (grad == 2) {  tl->DrawLatex(0.6, 0.92, "GRADE:  B");  fputs("Grade B\n", sumWrite); }
  if (grad == 3) {  tl->DrawLatex(0.6, 0.92, "GRADE:  C");  fputs("Grade C\n", sumWrite); }  


  sprintf(fname, "%s/gradingTest.txt", dirName);
  gradWrite = fopen(fname, "a");
 
  if (!gradWrite)
  {
    printf("\nmoduleSummary> !!!!!!!!!  ----> File %s does not exist yet...\n", fname);
    printf("moduleSummary> !!!!!!!!!  ----> Grading data could not be written to file!\n\n");
  }
  else
  {

    fputs(Form("Noise %i %i\n", fitsProblemB[0], fitsProblemC[0]), gradWrite);
    fputs(Form("VcalThrWidth %i %i\n", fitsProblemB[1], fitsProblemC[1]), gradWrite);
    fputs(Form("RelGainWidth %i %i\n", fitsProblemB[2], fitsProblemC[2]), gradWrite);
    fputs(Form("PedSpread %i %i\n", fitsProblemB[3], fitsProblemC[3]), gradWrite);
    fputs(Form("I150V %i %i\n", currentProblemB, currentProblemC), gradWrite);
    fputs(Form("Iratio %i 0\n",  slopeProblemB), gradWrite);
  }
  
  c1->SaveAs(Form("%s/moduleSummary_%s%s.ps", dirName, waf, test));
  c1->SaveAs(Form("%s/%s%s.gif", dirName, waf, test));

  printf("\nmoduleSummary> ................................................ finished\n");
}
예제 #8
0
//_________________________________________________________________________________________
Int_t checkPullTree(TString pathTree,  TString pathNameThetaMap, TString pathNameSigmaMap,
                    TString mapSuffix, const Int_t collType /*0: pp, 1: pPb, 2: PbPb*/, const Bool_t plotPull = kTRUE,
                    const Double_t downScaleFactor = 1,
                    TString pathNameSplinesFile = "", TString prSplinesName = "",
                    TString fileNameTree = "bhess_PIDetaTree.root", TString treeName = "fTree")
{
  const Bool_t isNonPP = collType != 0;
  const Double_t massProton = AliPID::ParticleMass(AliPID::kProton);
  
  Bool_t recalculateExpecteddEdx = pathNameSplinesFile != "";
  
  TFile* f = 0x0;
	
  f = TFile::Open(Form("%s/%s", pathTree.Data(), fileNameTree.Data()));
  if (!f)  {
    std::cout << "Failed to open tree file \"" << Form("%s/%s", pathTree.Data(), fileNameTree.Data()) << "\"!" << std::endl;
    return -1;
  }
      
  // Extract the data Tree
  TTree* tree = dynamic_cast<TTree*>(f->Get(treeName.Data()));
  if (!tree) {
    std::cout << "Failed to load data tree!" << std::endl;
    return -1;
  }
  
  // Extract the splines, if desired
  TSpline3* splPr = 0x0;
  if (recalculateExpecteddEdx) {
    std::cout << "Loading splines to recalculate expected dEdx!" << std::endl << std::endl;
    
    TFile* fSpl = TFile::Open(pathNameSplinesFile.Data());
    if (!fSpl) {
      std::cout << "Failed to open spline file \"" << pathNameSplinesFile.Data() << "\"!" << std::endl;
      return 0x0;
    }
    
    TObjArray* TPCPIDResponse = (TObjArray*)fSpl->Get("TPCPIDResponse");
    if (!TPCPIDResponse) {
      splPr = (TSpline3*)fSpl->Get(prSplinesName.Data());
      
      // If splines are in file directly, without TPCPIDResponse object, try to load them
      if (!splPr) {
        std::cout << "Failed to load object array from spline file \"" << pathNameSplinesFile.Data() << "\"!" << std::endl;
        return 0x0;
      }
    }
    else {
      splPr = (TSpline3*)TPCPIDResponse->FindObject(prSplinesName.Data());
      
      if (!splPr) {
        std::cout << "Failed to load splines from file \"" << pathNameSplinesFile.Data() << "\"!" << std::endl;
        return 0x0;
      }
    }
  }
  else
    std::cout << "Taking dEdxExpected from Tree..." << std::endl << std::endl;

  // Extract the correction maps
  TFile* fMap = TFile::Open(pathNameThetaMap.Data());
  if (!fMap)  {
    std::cout << "Failed to open thetaMap file \"" << pathNameThetaMap.Data() << "\"! Will not additionally correct data...." << std::endl;
  }

  TH2D* hMap = 0x0;
  
  if (fMap) {
    hMap = dynamic_cast<TH2D*>(fMap->Get(Form("hRefined%s", mapSuffix.Data())));
    if (!hMap) {
      std::cout << "Failed to load theta map!" << std::endl;
      return -1;
    }
  }

  TFile* fSigmaMap = TFile::Open(pathNameSigmaMap.Data());
  if (!fSigmaMap)  {
    std::cout << "Failed to open simgaMap file \"" << pathNameSigmaMap.Data() << "\"!" << std::endl;
    return -1;
  }

  TH2D* hThetaMapSigmaPar1 = dynamic_cast<TH2D*>(fSigmaMap->Get("hThetaMapSigmaPar1"));
  if (!hThetaMapSigmaPar1) {
    std::cout << "Failed to load sigma map for par 1!" << std::endl;
    return -1;
  }

  Double_t c0 = -1;
  TNamed* c0Info = dynamic_cast<TNamed*>(fSigmaMap->Get("c0"));
  if (!c0Info) {
    std::cout << "Failed to extract c0 from file with sigma map!" << std::endl;
    return -1;
  }

  TString c0String = c0Info->GetTitle();
  c0 = c0String.Atof();
  printf("Loaded parameter 0 for sigma: %f\n\n", c0);

  if (plotPull)
    std::cout << "Plotting pull..." << std::endl << std::endl;
  else
    std::cout << "Plotting delta'..." << std::endl << std::endl;

  Long64_t nTreeEntries = tree->GetEntriesFast();

  Double_t dEdx = 0.; // Measured dE/dx
  Double_t dEdxExpected = 0.; // Expected dE/dx according to parametrisation
  Double_t tanTheta = 0.; // Tangens of (local) theta at TPC inner wall
  Double_t pTPC = 0.; // Momentum at TPC inner wall
  UShort_t tpcSignalN = 0; // Number of clusters used for dEdx
  UChar_t  pidType = 0;
  Int_t    fMultiplicity = 0;
  //Double_t phiPrime = 0;

  // Only activate the branches of interest to save processing time
  tree->SetBranchStatus("*", 0); // Disable all branches
  tree->SetBranchStatus("pTPC", 1);
  tree->SetBranchStatus("dEdx", 1);
  tree->SetBranchStatus("dEdxExpected", 1);
  tree->SetBranchStatus("tanTheta", 1);
  tree->SetBranchStatus("tpcSignalN", 1);
  tree->SetBranchStatus("pidType", 1);
  //tree->SetBranchStatus("phiPrime", 1);
  if (isNonPP)
    tree->SetBranchStatus("fMultiplicity", 1);

  
  tree->SetBranchAddress("dEdx", &dEdx);
  tree->SetBranchAddress("dEdxExpected", &dEdxExpected);
  tree->SetBranchAddress("tanTheta", &tanTheta);
  tree->SetBranchAddress("tpcSignalN", &tpcSignalN);
  tree->SetBranchAddress("pTPC", &pTPC);
  tree->SetBranchAddress("pidType", &pidType);
  //tree->SetBranchAddress("phiPrime", &phiPrime);
  if (isNonPP)
    tree->SetBranchAddress("fMultiplicity", &fMultiplicity);

  
  // Output file
  TDatime daTime;
  TString savefileName = Form("%s%s_checkPullSigma_%04d_%02d_%02d__%02d_%02d.root", fileNameTree.ReplaceAll(".root", "").Data(),
                              recalculateExpecteddEdx ? "_recalcdEdx" : "",
                              daTime.GetYear(), daTime.GetMonth(), daTime.GetDay(), daTime.GetHour(), daTime.GetMinute());

  TFile* fSave = TFile::Open(Form("%s/%s", pathTree.Data(), savefileName.Data()), "recreate");
  if (!fSave) {
    std::cout << "Failed to open save file \"" << Form("%s/%s", pathTree.Data(), savefileName.Data()) << "\"!" << std::endl;
    return -1;
  }
  
  const Double_t pBoundLow = 0.1;
  const Double_t pBoundUp = 5;

  const Int_t nBins1 = TMath::Ceil(180 / downScaleFactor);
  const Int_t nBins2 = TMath::Ceil(100 / downScaleFactor);
  const Int_t nBins3 = TMath::Ceil(60 / downScaleFactor);
  
  const Int_t nPbinsForMap = nBins1 + nBins2 + nBins3;
  Double_t binsPforMap[nPbinsForMap + 1];
  
  Double_t binWidth1 = (1.0 - pBoundLow) / nBins1;
  Double_t binWidth2 = (2.0 - 1.0 ) / nBins2;
  Double_t binWidth3 = (pBoundUp - 2.0) / nBins3;
  
  for (Int_t i = 0; i < nBins1; i++)  {
    binsPforMap[i] = pBoundLow + i * binWidth1;
  }
  for (Int_t i = nBins1, j = 0; i < nBins1 + nBins2; i++, j++)  {
    binsPforMap[i] = 1.0 + j * binWidth2;
  }
  for (Int_t i = nBins1 + nBins2, j = 0; i < nBins1 + nBins2 + nBins3; i++, j++)  {
    binsPforMap[i] = 2.0 + j * binWidth3;
  }
  binsPforMap[nPbinsForMap] = pBoundUp;

  TH2D* hPull = new TH2D("hPull", "Pull vs. p_{TPC} integrated over tan(#Theta);p_{TPC} (GeV/c);Pull", nPbinsForMap, binsPforMap, 
                         plotPull ? 120 : 240, plotPull ? -6 : -0.6, plotPull ? 6 : 0.6);
  TH2D* hPullAdditionalCorr = (TH2D*)hPull->Clone("hPullAdditionalCorr");
  hPullAdditionalCorr->SetTitle("Pull vs. p_{TPC} integrated over tan(#Theta) with additional dEdx correction w.r.t. tan(#Theta)");
  /*
  const Int_t nThetaHistos = 3;
  TH2D* hPullTheta[nThetaHistos];
  TH2D* hPullAdditionalCorrTheta[nThetaHistos];
  Double_t tThetaLow[nThetaHistos] = { 0.0, 0.4, 0.9 };
  Double_t tThetaHigh[nThetaHistos] = { 0.1, 0.5, 1.0 };
  */
  const Int_t nThetaHistos = 10;
  TH2D* hPullTheta[nThetaHistos];
  TH2D* hPullAdditionalCorrTheta[nThetaHistos];
  Double_t tThetaLow[nThetaHistos] = { 0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9 };
  Double_t tThetaHigh[nThetaHistos] = { 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0 };
  

  for (Int_t i = 0; i < nThetaHistos; i++)    {
    hPullTheta[i] = new TH2D(Form("hPullTheta_%d", i),
                             Form("Pull vs. p_{TPC} for %.2f <= |tan(#Theta)| < %.2f;p_{TPC} (GeV/c);Pull", tThetaLow[i], tThetaHigh[i]),
                             nPbinsForMap, binsPforMap, plotPull ? 120 : 240, plotPull ? -6 : -0.6, plotPull ? 6 : 0.6);

    hPullAdditionalCorrTheta[i] =
      new TH2D(Form("hPullAdditionalCorrTheta_%d", i),
               Form("Pull vs. p_{TPC} for %.2f <= |tan(#Theta)| < %.2f with additional dEdx correction w.r.t. tan(#Theta);p_{TPC} (GeV/c);Pull",
                    tThetaLow[i], tThetaHigh[i]),
               nPbinsForMap, binsPforMap, plotPull ? 120 : 240, plotPull ? -6 : -0.6, plotPull ? 6 : 0.6);
  }

  
  
  
  
  
  TF1 corrFuncMult("corrFuncMult", "[0] + [1]*TMath::Max([4], TMath::Min(x, [3])) + [2] * TMath::Power(TMath::Max([4], TMath::Min(x, [3])), 2)",
                   0., 0.2);
  TF1 corrFuncMultTanTheta("corrFuncMultTanTheta", "[0] * (x -[2]) + [1] * (x * x - [2] * [2])", -1.5, 1.5);
  TF1 corrFuncSigmaMult("corrFuncSigmaMul", "TMath::Max(0, [0] + [1]*TMath::Min(x, [3]) + [2] * TMath::Power(TMath::Min(x, [3]), 2))", 0., 0.2);
  
  
  // LHC13b.pass2
  if (isNonPP)
    printf("Using corr Parameters for 13b.pass2\n!");
  
  corrFuncMult.SetParameter(0, -5.906e-06);
  corrFuncMult.SetParameter(1, -5.064e-04);
  corrFuncMult.SetParameter(2, -3.521e-02);
  corrFuncMult.SetParameter(3,  2.469e-02);
  corrFuncMult.SetParameter(4, 0);
  
  corrFuncMultTanTheta.SetParameter(0, -5.32e-06);
  corrFuncMultTanTheta.SetParameter(1,  1.177e-05);
  corrFuncMultTanTheta.SetParameter(2, -0.5);
  
  corrFuncSigmaMult.SetParameter(0, 0.);
  corrFuncSigmaMult.SetParameter(1, 0.);
  corrFuncSigmaMult.SetParameter(2, 0.);
  corrFuncSigmaMult.SetParameter(3, 0.);
  
  
  /* OK, but PID task was not very satisfying
  corrFuncMult.SetParameter(0, -6.27187e-06);
  corrFuncMult.SetParameter(1, -4.60649e-04);
  corrFuncMult.SetParameter(2, -4.26450e-02);
  corrFuncMult.SetParameter(3, 2.40590e-02);
  corrFuncMult.SetParameter(4, 0);
  
  corrFuncMultTanTheta.SetParameter(0, -5.338e-06);
  corrFuncMultTanTheta.SetParameter(1,  1.220e-05);
  corrFuncMultTanTheta.SetParameter(2, -0.5);
  
  corrFuncSigmaMult.SetParameter(0, 7.89237e-05);
  corrFuncSigmaMult.SetParameter(1, -1.30662e-02);
  corrFuncSigmaMult.SetParameter(2, 8.91548e-01);
  corrFuncSigmaMult.SetParameter(3, 1.47931e-02);
  */
  
  
  /*
  // LHC11a10a
  if (isNonPP)
    printf("Using corr Parameters for 11a10a\n!");
  
  corrFuncMult.SetParameter(0, 6.90133e-06);
  corrFuncMult.SetParameter(1, -1.22123e-03);
  corrFuncMult.SetParameter(2, 1.80220e-02);
  corrFuncMult.SetParameter(3, 0.1);
  corrFuncMult.SetParameter(4, 6.45306e-03);
  
  corrFuncMultTanTheta.SetParameter(0, -2.85505e-07);
  corrFuncMultTanTheta.SetParameter(1, -1.31911e-06);
  corrFuncMultTanTheta.SetParameter(2, -0.5);
  
  corrFuncSigmaMult.SetParameter(0, -4.29665e-05);
  corrFuncSigmaMult.SetParameter(1, 1.37023e-02);
  corrFuncSigmaMult.SetParameter(2, -6.36337e-01);
  corrFuncSigmaMult.SetParameter(3, 1.13479e-02);
  */
  
  /* OLD without saturation and large error for negative slopes
  corrFuncSigmaMult.SetParameter(0, -4.79684e-05);
  corrFuncSigmaMult.SetParameter(1, 1.49938e-02);
  corrFuncSigmaMult.SetParameter(2, -7.15269e-01);
  corrFuncSigmaMult.SetParameter(3, 1.06855e-02);
  */
  
  /* OLD very good try, but with fewer pBins for the fitting
  corrFuncMult.SetParameter(0, 6.88365e-06);
  corrFuncMult.SetParameter(1, -1.22324e-03);
  corrFuncMult.SetParameter(2, 1.81625e-02);
  corrFuncMult.SetParameter(3, 0.1);
  corrFuncMult.SetParameter(4, 6.36890e-03);
  
  corrFuncMultTanTheta.SetParameter(0, -2.85505e-07);
  corrFuncMultTanTheta.SetParameter(1, -1.31911e-06);
  corrFuncMultTanTheta.SetParameter(2, -0.5);
  
  corrFuncSigmaMult.SetParameter(0, -4.28401e-05);
  corrFuncSigmaMult.SetParameter(1, 1.24812e-02);
  corrFuncSigmaMult.SetParameter(2, -5.28531e-01);
  corrFuncSigmaMult.SetParameter(3, 1.25147e-02);
  */
  /*OLD good try
  corrFuncMult.SetParameter(0, 7.50321e-06);
  corrFuncMult.SetParameter(1, -1.25250e-03);
  corrFuncMult.SetParameter(2, 1.85437e-02);
  corrFuncMult.SetParameter(3, 0.1);
  corrFuncMult.SetParameter(4, 6.21192e-03);
  
  corrFuncMultTanTheta.SetParameter(0, -1.43112e-07);
  corrFuncMultTanTheta.SetParameter(1, -1.53e-06);
  corrFuncMultTanTheta.SetParameter(2, 0.3);
  
  corrFuncSigmaMult.SetParameter(0, -2.54019e-05);
  corrFuncSigmaMult.SetParameter(1, 8.68883e-03);
  corrFuncSigmaMult.SetParameter(2, -3.36176e-01);
  corrFuncSigmaMult.SetParameter(3, 1.29230e-02);
  */
  
  /*
  // LHC10h.pass2
  if (isNonPP)
    printf("Using corr Parameters for 10h.pass2\n!");
  
  corrFuncMult.SetParameter(0, 3.21636e-07);
  corrFuncMult.SetParameter(1, -6.65876e-04);
  corrFuncMult.SetParameter(2, 1.28786e-03);
  corrFuncMult.SetParameter(3, 1.47677e-02);
  corrFuncMult.SetParameter(4, 0.);
  
  corrFuncMultTanTheta.SetParameter(0, 7.23591e-08);
  corrFuncMultTanTheta.SetParameter(1, 2.7469e-06);
  corrFuncMultTanTheta.SetParameter(2, -0.5);
  
  corrFuncSigmaMult.SetParameter(0, -1.22590e-05);
  corrFuncSigmaMult.SetParameter(1, 6.88888e-03);
  corrFuncSigmaMult.SetParameter(2, -3.20788e-01);
  corrFuncSigmaMult.SetParameter(3, 1.07345e-02);
  */
  
  /*OLD bad try
  corrFuncMult.SetParameter(0, 2.71514e-07);
  corrFuncMult.SetParameter(1, -6.92031e-04);
  corrFuncMult.SetParameter(2, 3.56042e-03);
  corrFuncMult.SetParameter(3, 1.47497e-02);
  corrFuncMult.SetParameter(4, 0.);
  
  corrFuncMultTanTheta.SetParameter(0, 8.53204e-08);
  corrFuncMultTanTheta.SetParameter(1, 2.85591e-06);
  corrFuncMultTanTheta.SetParameter(2, -0.5);
  
  corrFuncSigmaMult.SetParameter(0, -6.82477e-06);
  corrFuncSigmaMult.SetParameter(1, 4.97051e-03);
  corrFuncSigmaMult.SetParameter(2, -1.64954e-01);
  corrFuncSigmaMult.SetParameter(3, 9.21061e-03);
  */
  

  //TODO NOW
  TF1* fShapeSmallP = new TF1("fShapeSmallP", "pol5", -0.4, 0.4);
  fShapeSmallP->SetParameters(1.01712, -0.0202725, -0.260692, 0.261623, 0.671854, -1.14014);
    
  for (Long64_t i = 0; i < nTreeEntries; i++) {
    tree->GetEntry(i);

    if (dEdx <= 0 || dEdxExpected <= 0 || tpcSignalN <= 10)
      continue;
    /*
    Double_t pT = pTPC*TMath::Sin(-TMath::ATan(tanTheta)+TMath::Pi()/2.0);
    if ((phiPrime > 0.072/pT+TMath::Pi()/18.0-0.035 && phiPrime < 0.07/pT/pT+0.1/pT+TMath::Pi()/18.0+0.035)) 
      continue;
    */
      
    if (pidType != kMCid) {
      if (pidType == kTPCid && pTPC > 0.6)
        continue;
      if (pidType == kTPCandTOFid && (pTPC < 0.6 || pTPC > 2.0))
        continue;
      if ((collType == 2) && pidType == kTPCandTOFid && pTPC > 1.0)
        continue;// Only V0's in case of PbPb above 1.0 GeV/c
      if (pidType == kV0idPlusTOFrejected) //TODO NOW NEW
        continue;
    }
    
    if (recalculateExpecteddEdx) {
      dEdxExpected = 50. * splPr->Eval(pTPC / massProton); //WARNING: What, if MIP is different from 50.? Seems not to be used (tested for pp, MC_pp, PbPb and MC_PbPb), but can in principle happen
    }
      
    //TODO NOW
    /*
    if (TMath::Abs(tanTheta) <= 0.4) {
      Double_t p0 = fShapeSmallP->Eval(tanTheta) - 1.0; // Strength of the correction
      Double_t p1 = -9.0; // How fast the correction is turned off
      Double_t p2 = -0.209; // Turn off correction around 0.2 GeV/c
      Double_t p3 = 1.0; // Delta' for large p should be 1

      Double_t corrFactor = TMath::Erf((pTPC + p2) * p1) * p0 + p3 + p0; // Add p0 to have 1 for p3 = 1 and large pTPC
      dEdxExpected *= corrFactor;
    }*/
    
     /*TODO old unsuccessful try 
    Double_t thetaGlobalTPC = -TMath::ATan(tanTheta) + TMath::Pi() / 2.;
    Double_t pTtpc = pTPC * TMath::Sin(thetaGlobalTPC);
    Double_t pTtpcInv = (pTtpc > 0) ? 1. / pTtpc : 0;
    Double_t p0 = 1.0;
    Double_t p1 = 1./ 0.5;//TODO 2.0;
    Double_t p2 = -0.2;//TODO 0.1
    Double_t pTcorrFactor = p0 + (pTtpcInv > p1) * p2 * (pTtpcInv - p1);
    
    dEdxExpected *= pTcorrFactor;
    */
    
      
    // From the momentum (via dEdxExpected) and the tanTheta of the track, the expected dEdx can be calculated (correctedDeDxExpected).
    // If the splines are correct, this should give in average the same value as dEdx. 
    // Now valid: Maps created from corrected data with splines adopted to corrected data, so lookup should be for dEdxExpected=dEdxSplines (no further
    // eta correction) or the corrected dEdx from the track (which should ideally be = dEdxSplines)
    
    // Tested with corrected data for LHC10d.pass2: using dEdx for the lookup (which is the corrected value and should ideally be = dEdxSplines):
    // Results almost the same. Maybe slightly better for dEdxExpected.
    
    // No longer valid: Note that the maps take always the uncorrected dEdx w.r.t.
    // tanTheta, so that correctedDeDxExpected is needed here normally. However, the information for the correction will be lost at some point.
    // Therefore, dEdxExpected can be used instead and should provide a good approximation.
    Double_t c1FromSigmaMap = hThetaMapSigmaPar1->GetBinContent(getBinX(hThetaMapSigmaPar1, tanTheta), getBinY(hThetaMapSigmaPar1, 1./dEdxExpected));
    
    Double_t expectedSigma = dEdxExpected * TMath::Sqrt( c0 * c0 + (c1FromSigmaMap * c1FromSigmaMap) / tpcSignalN);
    Double_t pull = (dEdx - dEdxExpected) / (plotPull ? expectedSigma: dEdxExpected);

    // Fill pull histo
    hPull->Fill(pTPC, pull);

    Double_t tanThetaAbs = TMath::Abs(tanTheta);
    
    for (Int_t j = 0; j < nThetaHistos; j++)    {
      if (tanThetaAbs  >= tThetaLow[j] && tanThetaAbs < tThetaHigh[j])  {
        hPullTheta[j]->Fill(pTPC, pull);
      }
    }

    if (!hMap)
      continue;

    Double_t correctionFactor = 1.;
    
    if (isNonPP) {
      // 1. Correct eta dependence
      correctionFactor = hMap->GetBinContent(getBinX(hMap, tanTheta), getBinY(hMap, 1./dEdxExpected));
      
      // 2. Correct for multiplicity dependence:
      Double_t multCorrectionFactor = 1.;
      
      if (fMultiplicity > 0) {
        Double_t relSlope = corrFuncMult.Eval(1. / (dEdxExpected * correctionFactor));
        relSlope += corrFuncMultTanTheta.Eval(tanTheta);

        multCorrectionFactor = 1. + relSlope * fMultiplicity;
      }

      c1FromSigmaMap = hThetaMapSigmaPar1->GetBinContent(getBinX(hThetaMapSigmaPar1, tanTheta), getBinY(hThetaMapSigmaPar1, 1./dEdxExpected));
      
      // Multiplicity dependence of sigma depends on the real dEdx at zero multiplicity, i.e. the eta (only) corrected dEdxExpected value has to be used
      // since all maps etc. have been created for ~zero multiplicity
      Double_t relSigmaSlope = corrFuncSigmaMult.Eval(1. / (dEdxExpected * correctionFactor));
      Double_t multSigmaCorrectionFactor = 1. + relSigmaSlope * fMultiplicity;
      
      dEdxExpected *= correctionFactor * multCorrectionFactor; 
      
      expectedSigma = dEdxExpected * TMath::Sqrt( c0 * c0 + (c1FromSigmaMap * c1FromSigmaMap) / tpcSignalN);
      expectedSigma *= multSigmaCorrectionFactor;
      
      pull = (dEdx - dEdxExpected) / (plotPull ? expectedSigma: dEdxExpected);
    }
    else {
      correctionFactor = hMap->GetBinContent(getBinX(hMap, tanTheta), getBinY(hMap, 1./dEdxExpected));
      
      c1FromSigmaMap = hThetaMapSigmaPar1->GetBinContent(getBinX(hThetaMapSigmaPar1, tanTheta), getBinY(hThetaMapSigmaPar1, 1./dEdxExpected));
   
      dEdxExpected *= correctionFactor; // If data is not corrected, but the sigma map is for corrected data, re-do analysis with corrected dEdx
      
      expectedSigma = dEdxExpected * TMath::Sqrt( c0 * c0 + (c1FromSigmaMap * c1FromSigmaMap) / tpcSignalN);
      pull = (dEdx - dEdxExpected) / (plotPull ? expectedSigma: dEdxExpected);
    }

    pull = (dEdx - dEdxExpected) / (plotPull ? expectedSigma: dEdxExpected);

    hPullAdditionalCorr->Fill(pTPC, pull);

    for (Int_t j = 0; j < nThetaHistos; j++)    {
      if (tanThetaAbs  >= tThetaLow[j] && tanThetaAbs < tThetaHigh[j])  {
        hPullAdditionalCorrTheta[j]->Fill(pTPC, pull);
      }
    }
  }
/*
  // Mean, Sigma, chi^2/NDF of pull of different theta bins and all in one plot
  TCanvas* canvPullMean = new TCanvas("canvPullMean", "canvPullMean", 100,10,1380,800);
  canvPullMean->SetLogx(kTRUE);
  canvPullMean->SetGridx(kTRUE);
  canvPullMean->SetGridy(kTRUE);
  TCanvas* canvPullSigma = new TCanvas("canvPullSigma", "canvPullSigma", 100,10,1380,800);
  canvPullSigma->SetLogx(kTRUE);
  canvPullSigma->SetGridx(kTRUE);
  canvPullSigma->SetGridy(kTRUE);
  TCanvas* canvPullChi2 = new TCanvas("canvPullChi2", "canvPullChi2", 100,10,1380,800);
  canvPullChi2->SetLogx(kTRUE);
  canvPullChi2->SetGridx(kTRUE);
  canvPullChi2->SetGridy(kTRUE);
  

  TCanvas* canvPull[nThetaHistos + 1];
  for (Int_t i = 0, j = nThetaHistos; i < nThetaHistos + 1; i++, j--)  {
    canvPull[i] = new TCanvas(Form("canvPull_%d", i), "canvPull", 100,10,1380,800);
    canvPull[i]->cd();
    canvPull[i]->SetLogx(kTRUE);
    canvPull[i]->SetLogz(kTRUE);
    canvPull[i]->SetGrid(kTRUE, kTRUE);

    TH2D* hTemp = 0x0;
    TString thetaString = "";
    if (i == nThetaHistos)  {
      hTemp = hPull;
      thetaString = "tan(#Theta) integrated";
    }
    else {
      hTemp = hPullTheta[i];
      thetaString = Form("%.2f #leq |tan(#Theta)| < %.2f", tThetaLow[i], tThetaHigh[i]);
    }
    
    normaliseHisto(hTemp);
    hTemp->FitSlicesY();
    hTemp->GetYaxis()->SetNdivisions(12);
    hTemp->GetXaxis()->SetMoreLogLabels(kTRUE);
    TH1D* hTempMean = (TH1D*)gDirectory->Get(Form("%s_1", hTemp->GetName()));
    hTempMean->SetTitle(Form("mean(pull), %s", thetaString.Data()));
    hTempMean->GetXaxis()->SetMoreLogLabels(kTRUE);
    hTempMean->SetLineWidth(2);
    hTempMean->SetMarkerStyle(20);
    TH1D* hTempSigma = (TH1D*)gDirectory->Get(Form("%s_2", hTemp->GetName()));
    hTempSigma->SetTitle(Form("#sigma(pull), %s", thetaString.Data()));
    hTempSigma->GetXaxis()->SetMoreLogLabels(kTRUE);
    hTempSigma->SetLineColor(kMagenta);
    hTempSigma->SetMarkerStyle(20);
    hTempSigma->SetMarkerColor(kMagenta);
    hTempSigma->SetLineWidth(2);
    TH1D* hTempChi2 = (TH1D*)gDirectory->Get(Form("%s_chi2", hTemp->GetName()));
    hTempChi2->SetTitle(Form("#chi^{2} / NDF (pull), %s", thetaString.Data()));
    hTempChi2->GetXaxis()->SetMoreLogLabels(kTRUE);
    hTempChi2->SetLineColor(kMagenta + 2);
    hTempChi2->SetMarkerStyle(20);
    hTempChi2->SetMarkerColor(kMagenta + 2);
    hTempChi2->SetLineWidth(2);

    hTemp->DrawCopy("colz");
    hTempMean->DrawCopy("same");
    hTempSigma->DrawCopy("same");
    hTempChi2->Scale(-1./10.);
    hTempChi2->DrawCopy("same");
    hTempChi2->Scale(-10.);

    canvPullMean->cd();
    hTempMean->SetLineColor(1 + ((j >= 9) ? (39 + 2 * (j - 9)) : j));
    hTempMean->SetMarkerColor(1 + ((j >= 9) ? (39 + 2 * (j - 9)) : j));
    hTempMean->DrawCopy((i == 0 ? "" : "same"));

    canvPullSigma->cd();
    hTempSigma->SetLineColor(1 + ((j >= 9) ? (39 + 2 * (j - 9)) : j));
    hTempSigma->SetMarkerColor(1 + ((j >= 9) ? (39 + 2 * (j - 9)) : j));
    hTempSigma->DrawCopy((i == 0 ? "" : "same"));

    canvPullChi2->cd();
    hTempChi2->SetLineColor(1 + ((j >= 9) ? (39 + 2 * (j - 9)) : j));
    hTempChi2->SetMarkerColor(1 + ((j >= 9) ? (39 + 2 * (j - 9)) : j));
    hTempChi2->DrawCopy((i == 0 ? "" : "same"));
  }

  canvPullMean->BuildLegend();
  canvPullSigma->BuildLegend();
  canvPullChi2->BuildLegend();
*/
  // Histograms with additional correction
  TCanvas* canvPullMeanCorr = 0x0;
  TCanvas* canvPullSigmaCorr = 0x0;
  TCanvas* canvPullChi2Corr = 0x0;
  TCanvas* canvPullCorr[nThetaHistos + 1];
  for (Int_t i = 0; i < nThetaHistos + 1; i++) 
    canvPullCorr[i] = 0x0;
  
  if (hMap) {
    // Mean, Sigma, chi^2/NDF of pull of different theta bins and all in one plot
    canvPullMeanCorr = new TCanvas("canvPullMeanCorr", "canvPullMeanCorr", 100,10,1380,800);
    canvPullMeanCorr->SetLogx(kTRUE);
    canvPullMeanCorr->SetGridx(kTRUE);
    canvPullMeanCorr->SetGridy(kTRUE);
    canvPullSigmaCorr = new TCanvas("canvPullSigmaCorr", "canvPullSigmaCorr", 100,10,1380,800);
    canvPullSigmaCorr->SetLogx(kTRUE);
    canvPullSigmaCorr->SetGridx(kTRUE);
    canvPullSigmaCorr->SetGridy(kTRUE);
    canvPullChi2Corr = new TCanvas("canvPullChi2Corr", "canvPullChi2Corr", 100,10,1380,800);
    canvPullChi2Corr->SetLogx(kTRUE);
    canvPullChi2Corr->SetGridx(kTRUE);
    canvPullChi2Corr->SetGridy(kTRUE);
    
    for (Int_t i = 0, j = nThetaHistos; i < nThetaHistos + 1; i++, j--)  {
      canvPullCorr[i] = new TCanvas(Form("canvPullCorr_%d", i), "canvPullCorr", 100,10,1380,800);
      canvPullCorr[i]->cd();
      canvPullCorr[i]->SetLogx(kTRUE);
      canvPullCorr[i]->SetLogz(kTRUE);
      canvPullCorr[i]->SetGrid(kTRUE, kTRUE);

      TH2D* hTemp = 0x0;
      TString thetaString = "";
      
      if (i == nThetaHistos)  {
        hTemp = hPullAdditionalCorr;
        thetaString = "tan(#Theta) integrated";
      }
      else    {
        hTemp = hPullAdditionalCorrTheta[i];
        thetaString = Form("%.2f #leq |tan(#Theta)| < %.2f", tThetaLow[i], tThetaHigh[i]);
      }

      normaliseHisto(hTemp);
      hTemp->FitSlicesY();
      hTemp->GetYaxis()->SetNdivisions(12);
      hTemp->GetXaxis()->SetMoreLogLabels(kTRUE);
      TH1D* hTempMean = (TH1D*)gDirectory->Get(Form("%s_1", hTemp->GetName()));
      hTempMean->SetTitle(Form("mean(pull), %s", thetaString.Data()));
      hTempMean->GetXaxis()->SetMoreLogLabels(kTRUE);
      hTempMean->SetLineWidth(2);
      hTempMean->SetMarkerStyle(20);
      TH1D* hTempSigma = (TH1D*)gDirectory->Get(Form("%s_2", hTemp->GetName()));
      hTempSigma->SetTitle(Form("#sigma(pull), %s", thetaString.Data()));
      hTempSigma->GetXaxis()->SetMoreLogLabels(kTRUE);
      hTempSigma->SetLineColor(kMagenta);
      hTempSigma->SetMarkerStyle(20);
      hTempSigma->SetMarkerColor(kMagenta);
      hTempSigma->SetLineWidth(2);
      TH1D* hTempChi2 = (TH1D*)gDirectory->Get(Form("%s_chi2", hTemp->GetName()));
      hTempChi2->SetTitle(Form("#chi^{2} / NDF (pull), %s", thetaString.Data()));
      hTempChi2->GetXaxis()->SetMoreLogLabels(kTRUE);
      hTempChi2->SetLineColor(kMagenta + 2);
      hTempChi2->SetMarkerStyle(20);
      hTempChi2->SetMarkerColor(kMagenta + 2);
      hTempChi2->SetLineWidth(2);

      hTemp->DrawCopy("colz");
      hTempMean->DrawCopy("same");
      hTempSigma->DrawCopy("same");
      hTempChi2->Scale(-1./10.);
      hTempChi2->DrawCopy("same");
      hTempChi2->Scale(-10.);
  
      canvPullMeanCorr->cd();
      hTempMean->SetLineColor(1 + ((j >= 9) ? (39 + 2 * (j - 9)) : j));
      hTempMean->SetMarkerColor(1 + ((j >= 9) ? (39 + 2 * (j - 9)) : j));
      hTempMean->DrawCopy((i == 0 ? "" : "same"));
      
      canvPullSigmaCorr->cd();
      hTempSigma->SetLineColor(1 + ((j >= 9) ? (39 + 2 * (j - 9)) : j));
      hTempSigma->SetMarkerColor(1 + ((j >= 9) ? (39 + 2 * (j - 9)) : j));
      hTempSigma->DrawCopy((i == 0 ? "" : "same"));
      
      canvPullChi2Corr->cd();
      hTempChi2->SetLineColor(1 + ((j >= 9) ? (39 + 2 * (j - 9)) : j));
      hTempChi2->SetMarkerColor(1 + ((j >= 9) ? (39 + 2 * (j - 9)) : j));
      hTempChi2->DrawCopy((i == 0 ? "" : "same"));
    }
    
    canvPullMeanCorr->BuildLegend();
    canvPullSigmaCorr->BuildLegend();
    canvPullChi2Corr->BuildLegend();
  }
  
  
  
  
  
  fSave->cd();
  /*canvPullMean->Write();
  canvPullSigma->Write();
  canvPullChi2->Write();
  
  for (Int_t  i = 0; i < nThetaHistos + 1; i++) {
    canvPull[i]->Write();
  }*/
  
  canvPullMeanCorr->Write();
  canvPullSigmaCorr->Write();
  canvPullChi2Corr->Write();
  
  for (Int_t  i = 0; i < nThetaHistos + 1; i++) {
    canvPullCorr[i]->Write();
  }

  TNamed* info = new TNamed(Form("Theta map: %s\n\nSigma map: %s\n\nSplines file: %s\n\nSplines name: %s", pathNameThetaMap.Data(), 
                                 pathNameSigmaMap.Data(), pathNameSplinesFile.Data(), prSplinesName.Data()),
                            "info");
  info->Write();
  fSave->Close();
  
  return 0;
}
TCanvas* pHitSpecPosGen( )
{
  TCanvas* c = new TCanvas("cHitSpecPosGen","cHitSpecPosGen",1200,600);
  c->Divide(2,1);
  TVirtualPad* p; TH2D *h; TH2D *hAtPhi0;
  TText t; t.SetTextColor(4);

  p =c->cd(1); p->SetLogy(); p->SetGrid(0,1);
  h = (TH2D*)gROOT->FindObject("hHitSpec_PtVsPhiGen_Minus"); 
  hAtPhi0 = (TH2D*)gROOT->FindObject("hHitSpec_PtVsPhiGenAtPhi0_Minus"); 
  h->GetYaxis()->SetRange(4,33);
  h->GetXaxis()->SetNdivisions(505); h->GetXaxis()->SetLabelSize(0.04);
  h->DrawCopy("box");
  hAtPhi0->SetLineColor(2);
  hAtPhi0->DrawCopy("box same");
  t.DrawTextNDC(0.17,0.15, "BARREL MU MINUS");
  std::cout <<h->GetTitle() << std::endl;
  for (int iy = 1; iy <=h->GetNbinsY(); iy++) {
  std::cout <<" pt: " << h->GetYaxis()->GetBinLowEdge(iy);
  double xmin=100.;
  double xAtMax = 0.; double valAtMax = 0.;
  double xmax=-100.;
  for (int ix = 1; ix <=h->GetNbinsX(); ix++) {
     double val = h->GetBinContent(ix,iy); 
     double xbmin = h->GetXaxis()->GetBinLowEdge(ix);
     double xcent = h->GetXaxis()->GetBinCenter(ix);
     double xbmax = h->GetXaxis()->GetBinUpEdge(ix);
     if (val > valAtMax) { valAtMax = val; xAtMax = xcent; }
     if (val > 1 && (xbmin < xmin)) xmin = xbmin;    
     if (val > 1 && (xbmax > xmax)) xmax = xbmax;    
  }
  std::cout <<"  set DPHI0 = "<<1.025-xAtMax 
            <<"; set DPHI_MARGIN = " <<std::max( (xAtMax-xmin), (xmax-xAtMax))
<<";" << std::endl;
  }

  p =c->cd(2); p->SetLogy(); p->SetGrid(1,1);
  h = (TH2D*)gROOT->FindObject("hHitSpec_PtVsPhiGen_Plus"); 
  hAtPhi0 = (TH2D*)gROOT->FindObject("hHitSpec_PtVsPhiGenAtPhi0_Plus"); 
  h->GetYaxis()->SetRange(4,32);
  h->GetXaxis()->SetNdivisions(505); h->GetXaxis()->SetLabelSize(0.04);
  h->DrawCopy("box");
  hAtPhi0->SetLineColor(2);
  hAtPhi0->DrawCopy("box same");
  t.DrawTextNDC(0.17,0.15, "BARREL MU PLUS");
  std::cout <<h->GetTitle() << std::endl;
  for (int iy = 1; iy <=h->GetNbinsY(); iy++) {
  std::cout <<" pt: " << h->GetYaxis()->GetBinLowEdge(iy);
  double xmin=100.;
  double xAtMax = 0.; double valAtMax = 0.;
  double xmax=-100.;
  for (int ix = 1; ix <=h->GetNbinsX(); ix++) {
     double val = h->GetBinContent(ix,iy); 
     double xbmin = h->GetXaxis()->GetBinLowEdge(ix);
     double xcent = h->GetXaxis()->GetBinCenter(ix);
     double xbmax = h->GetXaxis()->GetBinUpEdge(ix);
     if (val > valAtMax) { valAtMax = val; xAtMax = xcent; }
     if (val > 1 && (xbmin < xmin)) xmin = xbmin;    
     if (val > 1 && (xbmax > xmax)) xmax = xbmax;    
  }
  std::cout <<"  set DPHI0 = "<<1.025-xAtMax 
            <<"; set DPHI_MARGIN = " <<std::max( (xAtMax-xmin), (xmax-xAtMax))
<<";" << std::endl;
  }

  return c;
}
void GradeCorrelation(double prob = 0.10, int nCut = 50) {
	
	std::cout << "Starting Grade Correlation..." << std::endl;
	TBenchmark* myBenchmark = new TBenchmark();
	
	myBenchmark->Start("NormMap");
	// Get the student TTree prepared in another macro.
	if (MyFunctions::gradeNormMap.size() == 0)
		MyFunctions::BuildGradeNormMap();
	myBenchmark->Stop("NormMap");
	
	std::cout << "Made GradeNormMap..." << std::endl;
	
	// Just a quick look at the data in the Students TTree
	TFile* f = new TFile("Students.root");
	TTree* studentTree = (TTree*)f->Get("Students");
	Student* student = 0;
	studentTree->SetBranchAddress("student", &student);
	
	Long64_t nentries = studentTree->GetEntriesFast();
	
	std::cout << "Entries in Students TTree = " << nentries << std::endl;
	
	// We want to loop over students and look at pairs of courses taken in different semesters to see if there is
	// any correlation between graede performance.
	
	std::map<std::pair<TString, TString>, CorrelationCalculator> corrMap;
	
//	nentries = 1000;
	
	myBenchmark->Start("Main Loop");
	int nPairAll = 0;
	for (Long64_t jentry = 0; jentry < nentries; ++jentry) {
		studentTree->GetEntry(jentry);
		if (jentry % 1000 == 0)
			std::cout << "At student " << jentry << std::endl;
//		std::cout << "Looking at student " << student->Id() << std::endl;
		student->Finalize();  // Regenerates non-persisted references
		int nTerms = student->Enrollments().size();
//		std::cout << "nTerms = " << nTerms << std::endl;
		
		for (int iTerm = 0; iTerm < nTerms - 1; ++iTerm) {
			const Student::Enrollment iEnrollment = student->Enrollments()[iTerm];
			if (!MyFunctions::regularSemester(iEnrollment.term)) continue;
			for (Student::Grade iGrade : iEnrollment.grades) {
				if (!MyFunctions::ValidGrade(iGrade.grade)) continue;
				// Get a prediction for this grade using norm-corrected grades
//				std::cout << "1" << std::endl;
				double prediction_i = student->CourseGradePrediction(iGrade, Student::DISTRIBUTION);
//				std::cout << "2" << std::endl;
				double delta_i = iGrade.quality - prediction_i;
			
				// Find next regular term only
				bool foundRegTerm = false;
				for (int jTerm = iTerm + 1; jTerm < nTerms && !foundRegTerm; ++jTerm) {
					const Student::Enrollment jEnrollment = student->Enrollments()[jTerm];
					if (!MyFunctions::regularSemester(jEnrollment.term)) continue;
					foundRegTerm = true;
					for (Student::Grade jGrade : jEnrollment.grades) {
						if (jGrade.course == iGrade.course) continue;
						if (!MyFunctions::ValidGrade(jGrade.grade)) continue;
						
						double prediction_j = student->CourseGradePrediction(jGrade, Student::DISTRIBUTION);
						double delta_j = jGrade.quality - prediction_j;
						
						corrMap[std::make_pair(iGrade.course, jGrade.course)].Add(delta_i, delta_j);
						++nPairAll;
						
					}
				}
			} 
		}
		
	}
	myBenchmark->Stop("Main Loop");
	
	std::cout << "nPairAll     = " << nPairAll << std::endl;
	std::cout << "Unique Pairs = " << corrMap.size() << std::endl;
	
	TH1D* rHist = new TH1D("rHist", "Correlation Coefficient, #rho", 120, -1.2, 1.2);
	TH1D* pHist = new TH1D("pHist", "Probablity Distribution", 100, 0., 1.);
	TH1D* nHist = new TH1D("nHist", "Number of entries", 100, 0., 2000.);
	TH2D* pVrHist = new TH2D("pVrHist", "Prob vs. #rho", 100, -1., 1., 100, 0., 1.);
	
	myBenchmark->Start("Prune");
	for (auto iter = corrMap.begin(); iter != corrMap.end();) {
		if (iter->second.n() < nCut) {
			corrMap.erase(iter++);
			continue;
		}
		double p = iter->second.p();
		double r = iter->second.r();

		// Test for nan?
		if (p != p) {
			std::cout << "Found p = nan: n = " << iter->second.n() << std::endl;
			corrMap.erase(iter++);
			continue;
		}
		if (p < 0.) {
			corrMap.erase(iter++);
			continue;
		}
		rHist->Fill(r);
		pHist->Fill(p);
		nHist->Fill(iter->second.n());
		pVrHist->Fill(r, p);
		if (p < 1. - prob && p > prob) {
			corrMap.erase(iter++);
		}
		else {
			std::cout << "r = " << iter->second.r() << ", p = " << p << std::endl;
			++iter;
		}
	}
	myBenchmark->Stop("Prune");
	std::cout << "Post Cut     = " << corrMap.size() << std::endl;
	
	myBenchmark->Start("Sort");
	std::vector<std::pair<std::pair<TString, TString>, CorrelationCalculator>> corrVec(corrMap.begin(), corrMap.end());
	std::sort(corrVec.begin(), corrVec.end(), &sortFunc);
	myBenchmark->Stop("Sort");
	
	int printTop = 50;
	int printed = 0;
	for (auto const& entry : corrVec) {
		std::cout << entry.first.first << " : " << entry.first.second << "\t, n = " << entry.second.n() << "\t, r = " << entry.second.r() 
			<< "\t, p = " << entry.second.p() << std::endl;
		++printed;
		if (printed >= printTop) break;
	}

	TCanvas* c1 = new TCanvas("c1", "Grade Correlation", 1600, 1200);
	c1->Divide(2,2);
	c1->cd(1);
	TF1* myGaus = new TF1("myGaus", "gaus", -1., 1.);
	myGaus->SetParameters(600., 0., 0.2);
	myGaus->FixParameter(1, 0.);
	rHist->Fit(myGaus, "0B", "", -1., 0.);
	rHist->DrawCopy();
	myGaus->DrawCopy("SAME");
	c1->cd(2);
	pHist->DrawCopy();
	c1->cd(3);
	nHist->DrawCopy();
	c1->cd(4);
	pVrHist->DrawCopy();
	
	float rt, cp;
	myBenchmark->Summary(rt, cp);
	
}