Ejemplo n.º 1
0
void Draw_KL_Test(){

  TChain* ch = new TChain("Tree");
  TChain* ch1 = new TChain("Tree");
  
  TH1D* his  = new TH1D("Klong6g","Klong6g",20,450,550);
  TH1D* his1 = new TH1D("Klong4g","Klong4g",20,450,550);
  TH1D* his2 = new TH1D("Klong4gAll","Klong4gAll",60,250,550);

  for( int i = 0; i< 68; i++){
    ch->Add(Form("klongRootFile/kl%d.root" ,4162+i));
    ch1->Add(Form("klongRootFile/ks%d.root",4162+i));
  }
  ch->Project(his->GetName()  ,"KlongMass[0]","CutCondition==0");
  ch1->Project(his1->GetName(),"KlongMass[0]","CutCondition==0");
  ch1->Project(his2->GetName(),"KlongMass[0]","CutCondition==0");
  
  TF1* func = new TF1("func","gaus(0)+expo(3)",0,550);
  func->SetParameter(1,498);
  func->SetParameter(2,5);
  TF1* func2 = new TF1("func2","gaus(0)",0,550);
  func2->SetParameter(1,498);
  func2->SetParameter(2,5);



  TCanvas* can = new TCanvas("can","",1200,600);
  can->Divide(2,1);
  can->cd(1);
  his2->Fit(func->GetName(),"","",450,550);
  his2->Draw();
  TF1* func1 = new TF1("Test","gaus",450,550);
  func1->SetParameter(0,func->GetParameter(0));
  func1->SetParameter(1,func->GetParameter(1));
  func1->SetParameter(2,func->GetParameter(2));

  can->cd(2);
  his1->SetLineColor(2);  
  his->Draw();
  his->Fit(func2->GetName(),"","",450,550);
  func->Draw("same");
  his1->Draw("same");

  std::cout<< func2->GetParameter(0) << " " 
	   << func->GetParameter(0)  << " " 
	   << func->GetParameter(0)/func2->GetParameter(0)<< std::endl;
  std::cout<< func2->Integral(450,550) << " " 
	   << func1->Integral(450,550)  << " " 
	   << func1->Integral(450,550)/func2->Integral(450,550)
	   << std::endl;
  //ch->Draw("KlongPt[0]:KlongMass[0]>>(400,200,600,50,0,20)","(CutCondition&(1|2|4|8))==0","colz");
  gPad->SetLogz();
  TText* text = new TText(0.5,0.5,"");
  TText* text1 = new TText(0.5,0.5,"");
  text->DrawTextNDC(0.5,0.5,Form("Integral:%2.3lf",func1->Integral(450,550)));
  text1->DrawTextNDC(0.5,0.6,Form("Integral:%2.3lf",func2->Integral(450,550)));
  
}
void FitWithConstant(TH1D* h1, TFile *out)
{
  Double_t fitRangeLow = 0.;
  Double_t fitRangeHigh = .4;
  TF1 *f = new TF1("f","[0]", fitRangeLow, fitRangeHigh);

  Int_t binLow = h1->FindBin(fitRangeLow);
  Int_t binHigh = h1->FindBin(fitRangeHigh);
  cout<<"\t\t********************Fitting with a constant value********************"<<endl<<endl;;
  h1->Fit(f, "R0");

  TString fitName = h1->GetName();
  fitName += "Fit";
  f->SetName(fitName);
  f->SetTitle(fitName);

  // TFile out("Compare.root","update");
  TDirectory *dir = out->GetDirectory("Fit");
  if(!dir) dir = out->mkdir("Fit");
  dir->cd();
  // f->SetDirectory(0); 
  f->Write(f->GetName(), TObject::kOverwrite);
  // out->Close();
}
Ejemplo n.º 3
0
int makeInvMassHistosNoBGKK(){
    //Set global style stuff
    gROOT->Reset();
    gROOT->SetStyle("Plain");
    gStyle->SetPalette(1);
    gStyle->SetCanvasColor(kWhite);
    gStyle->SetCanvasBorderMode(0);
    gStyle->SetPadBorderMode(0);
    gStyle->SetTitleBorderSize(0);
    gStyle->SetOptStat(0);
    gStyle->SetOptFit(1);
    gStyle->SetErrorX(0);
    gStyle->SetTitleW(0.9);
    gStyle->SetTitleSize(0.05, "xyz");
    gStyle->SetTitleSize(0.06, "h");

    int NUM_PT_BINS = 20;
    int NUM_MASS_BINS = 1000;
    double MASS_LOW = 0.0;
    double MASS_HIGH = 2.0;
    string particles [8];
    particles[0] = "K*^{+} + K*^{0}";
    particles[1] = "K*^{-} + #bar{K}*^{0}";
    particles[2] = "K*^{+}";
    particles[3] = "K*^{-}";
    particles[4] = "K*^{0}";
    particles[5] = "#bar{K}*^{0}";
    particles[6] = "K*^{0} + #bar{K}*^{0}";
    particles[7] = "K*^{+} + K*^{-}";
//at decay point
//    string folder = "/Users/jtblair/Downloads/kstar_data/decayed/pt02/";
//reconstructed
    string folder = "/Users/jtblair/Downloads/kstar_data/reconstructed/pt02/";

    string files[20];
    files[0] = "invm_[0.0,0.2].dat";
    files[1] = "invm_[0.2,0.4].dat";
    files[2] = "invm_[0.4,0.6].dat";
    files[3] = "invm_[0.6,0.8].dat";
    files[4] = "invm_[0.8,1.0].dat";
    files[5] = "invm_[1.0,1.2].dat";
    files[6] = "invm_[1.2,1.4].dat";
    files[7] = "invm_[1.4,1.6].dat";   
    files[8] = "invm_[1.6,1.8].dat";
    files[9] = "invm_[1.8,2.0].dat";
    files[10] = "invm_[2.0,2.2].dat";
    files[11] = "invm_[2.2,2.4].dat";
    files[12] = "invm_[2.4,2.6].dat";
    files[13] = "invm_[2.6,2.8].dat";
    files[14] = "invm_[2.8,3.0].dat";
    files[15] = "invm_[3.0,3.2].dat";
    files[16] = "invm_[3.2,3.4].dat";
    files[17] = "invm_[3.4,3.6].dat";
    files[18] = "invm_[3.6,3.8].dat";
    files[19] = "invm_[3.8,4.0].dat";
/*
    string files[8];
    files[0] = "invm_[0.0,0.5].dat";
    files[1] = "invm_[0.5,1.0].dat";
    files[2] = "invm_[1.0,1.5].dat";
    files[3] = "invm_[1.5,2.0].dat";
    files[4] = "invm_[2.0,2.5].dat";
    files[5] = "invm_[2.5,3.0].dat";
    files[6] = "invm_[3.0,3.5].dat";
    files[7] = "invm_[3.5,4.0].dat";
*/

    Int_t PARTICLE_NUM = 5;

    TFile *output = new TFile("20170721_KKbarAdded2_fixedwidth42_recon_pf100_scaled_error05.root", "RECREATE");

    TH1D *kstar0mass = new TH1D("kstar0mass", Form("Fit value of M*_{0} vs. p_{T} for %s", particles[PARTICLE_NUM].c_str()), NUM_PT_BINS, 0.0, 4.0);
    TH1D *kstar0width = new TH1D("kstar0width", Form("#Gamma_{tot}(M=M*_{0}) vs p_{T} for %s", particles[PARTICLE_NUM].c_str()), NUM_PT_BINS, 0.0, 4.0);
    TH1D *kstar0collWidth = new TH1D("kstar0collWidth", Form("Fit value of #Gamma_{coll} component vs. p_{T} for %s", particles[PARTICLE_NUM].c_str()), NUM_PT_BINS,0.0, 4.0);
    TH1D *kstar0decWidth = new TH1D("kstar0decWidth", Form("#Gamma_{dec}(M=M*_{0}) component vs. p_{T} for %s;p_{T} (GeV/c);Width (GeV/c^2)", particles[PARTICLE_NUM].c_str()), NUM_PT_BINS,0.0, 4.0);
   
    kstar0mass->GetXaxis()->SetTitle("p_{T} (GeV/c)");
    kstar0mass->GetYaxis()->SetTitle("Mass (GeV/c^{2})");
    kstar0width->GetXaxis()->SetTitle("p_{T} (GeV/c)");
    kstar0width->GetYaxis()->SetTitle("Width (GeV/c^2)");
    kstar0collWidth->GetXaxis()->SetTitle("p_{T} (GeV/c)");
    kstar0collWidth->GetYaxis()->SetTitle("Width (GeV/c^2)");

    kstar0mass->SetStats(kFALSE);
    kstar0width->SetStats(kFALSE);
    kstar0collWidth->SetStats(kFALSE);
    kstar0decWidth->SetStats(kFALSE);

    TF1 *massline = new TF1("massline", "[0]", 0.0, 4.0);
    massline->SetParameter(0, 0.892);
    massline->SetLineColor(2);
    massline->SetLineStyle(7);

    TF1 *widthline = new TF1("widthline", "[0]", 0.0, 4.0);
    widthline->SetParameter(0, 0.042);

    double mass = 0.0, width = 0.0, collWidth = 0.0, massBG=0.0;
    double massError = 0.0, widthError= 0.0, collWidthError = 0.0, massBGError=0.0;

    TCanvas *canvas[9];
    TCanvas *diffCanvas[9];
    TPaveStats *st;
    TPad *pad;

    //ofstream integrals;
    //integrals.open("kstarbar_integrals.txt");

    for(int nfile = 0; nfile < NUM_PT_BINS; nfile++){
        double meanPT = (double)(nfile*2+1)/10.0;
        string filename = folder+files[nfile];
        string ptLower = filename.substr(filename.find("[")+1, 3);
        string ptHigher = filename.substr(filename.find(",")+1, 3);   
        TH1D* histos[8];
        TH1D* newHistos[8];
        TH1D* diffHistos[8];
        TH1D* bg[8];
        for(int i=0; i<8; i++){
            if(nfile<5){
                histos[i] = new TH1D(Form("ptbin0%dparticle%d",nfile*2+1, i), Form("Invariant Mass for (%s), %s < p_{T} < %s",particles[i].c_str(), ptLower.c_str(), ptHigher.c_str()), NUM_MASS_BINS, MASS_LOW, MASS_HIGH);
            newHistos[i] = new TH1D(Form("newptbin0%dparticle%d",nfile*2+1, i), Form("Invariant Mass for (%s), %s < p_{T} < %s",particles[i].c_str(), ptLower.c_str(), ptHigher.c_str()), 250, MASS_LOW, MASS_HIGH);

            }else{
                histos[i] = new TH1D(Form("ptbin%dparticle%d",nfile*2+1, i), Form("Invariant Mass for (%s), %s < p_{T} < %s",particles[i].c_str(), ptLower.c_str(), ptHigher.c_str()), NUM_MASS_BINS, MASS_LOW, MASS_HIGH);
                newHistos[i] = new TH1D(Form("newptbin%dparticle%d",nfile*2+1, i), Form("Invariant Mass for (%s), %s < p_{T} < %s",particles[i].c_str(), ptLower.c_str(), ptHigher.c_str()), 250, MASS_LOW, MASS_HIGH);

            }
            histos[i]->GetXaxis()->SetTitle("Invariant Mass (GeV/c^{2})");
            histos[i]->GetYaxis()->SetTitle("Counts");
        }

        ifstream input;
        input.open(filename.c_str());
        string line = "";
        if(input.good()){
            getline(input, line);
        }

        double massBin=0.0;
        double invMass[8];
        for(int i=0; i<8; i++){
            invMass[i] = 0.0;
        }
        int lineNumber = 1;
        while(1){
            input >> massBin >> invMass[0] >> invMass[1] >> invMass[2] >> invMass[3] >> invMass[4] >> invMass[5] >> invMass[6] >> invMass[7];
            if(!input.good())break;
            for(int i =0; i<8; i++){
                histos[i]->SetBinContent(lineNumber, invMass[i]/500.0);
            }
            if(lineNumber > 440 && lineNumber < 460 && nfile==6){
//               printf("mass: %.12f invMass[6]: %.12f\n", massBin, invMass[6]);
            }
            lineNumber++;
        }
         

        printf("****** Fits for file: %s ******\n", filename.c_str());
        for(int i=PARTICLE_NUM; i<PARTICLE_NUM+1; i++){
           
            //add the K*0 distribution to the K*0bar (K*0 = 4 for decay, K*0 = 3 for reconstructed)
            histos[i]->Add(histos[3]);
            if(nfile==0){
                canvas[i] = new TCanvas(Form("c%i", i),Form("c%i", i), 0,0,900,900);
                canvas[i]->Divide(5,4);
                diffCanvas[i] = new TCanvas(Form("diffC%i", i),Form("diffC%i", i), 0,0,900,900);
                diffCanvas[i]->Divide(5,4);
            }
            //rebin
            //histos[i]->Sumw2();
            histos[i]->Rebin(4);

            //Fixing the errors to a percentage of the signal region:
            for(int ibin=1; ibin < histos[i]->GetNbinsX(); ibin++){
                histos[i]->SetBinError(ibin, histos[i]->GetBinContent((int)(0.892*(250.0/2.0)))*0.05);
                newHistos[i]->SetBinContent(ibin, histos[i]->GetBinContent(ibin));
                newHistos[i]->SetBinError(ibin, histos[i]->GetBinError(ibin));
            }
            
            pad = (TPad*)canvas[i]->cd(nfile+1);
            histos[i]->SetLineColor(1);
            histos[i]->SetLineWidth(1);
            histos[i]->GetXaxis()->SetRangeUser(0.7, 1.2);
            histos[i]->GetYaxis()->SetRangeUser(0, 1.5*histos[i]->GetBinContent(histos[i]->GetMaximumBin()));
            //histos[i]->SetStats(kFALSE);
            
            //histos[i]->Draw("HIST");

            printf("mean PT: %f\n", meanPT);

            TF1 *fit = new TF1(Form("fitPTbin%d00particle%d", nfile*2+1, i), FitFunRelBW, 0.68, 1.05, 5);
            //TF1 *fit = new TF1(Form("fitPTbin%d00particle%d", nfile*2+1, i), "gaus(0)", 0.86, 0.92);


            fit->SetParNames("BW Area", "Mass", "Width", "PT", "Temp");
            fit->SetParameters(TMath::Power(10.0, (float)(nfile)/1.7), 0.89, 0.1, 0.5, 0.130);
            //fit->SetParNames("BW Area", "Mass", "Width");
            //fit->SetParameters(100, 0.89, 0.0474);
            //fit->SetParLimits(0, -10, 1.5e9);
            Float_t max = histos[i]->GetXaxis()->GetBinCenter(histos[i]->GetMaximumBin());
            //if(max < 0.91 && max > 0.892){
            //    fit->SetParLimits(1, max-0.001, max+0.001);
            //}else{
                fit->SetParLimits(1, 0.82, 0.98);
            //}
            //fit->SetParLimits(2, 0.005, 0.15);
            fit->FixParameter(2, 0.042);
            fit->FixParameter(3, meanPT);
            //fit->SetParLimits(4, 0.05, 0.2);
            fit->FixParameter(4, 0.100001);
            fit->SetLineColor(2);

            printf("%s\n", fit->GetName());

            histos[i]->Fit(Form("fitPTbin%d00particle%d", nfile*2+1, i), "BRIM", "SAME");
            TVirtualFitter *fitter = TVirtualFitter::GetFitter();
           
            histos[i]->SetStats(1);
            histos[i]->Draw();
            gPad->Update();
            pad->Update();
            st = (TPaveStats*)histos[i]->FindObject("stats");
            st->SetX1NDC(0.524);
            st->SetY1NDC(0.680);
            st->SetX2NDC(0.884);
            st->SetY2NDC(0.876);
            //fit->Draw("SAME");
            //histos[i]->Draw();
            gPad->Update();
            pad->Update();
            printf("\n");
    
            diffHistos[i] = (TH1D*)histos[i]->Clone(Form("diffPTbin%d00particl%d", nfile*2+1, i));
            diffHistos[i]->Add(fit, -1);
            diffCanvas[i]->cd(nfile+1);
            diffHistos[i]->Draw("HIST E");
            diffHistos[i]->Write();

            //counting bins
            Float_t integral = histos[i]->Integral(1, 500)*500.0;
            //integrals << integral <<" \n";
            histos[i]->Write();
            fit->Write();
            //Do mass and width vs. pT plots just for K*0
            if(i==PARTICLE_NUM){
                mass = fit->GetParameter(1);
                massError = fit->GetParError(1);

                collWidth = fit->GetParameter(2);
                collWidthError = fit->GetParError(2);

                width = Gamma(mass, collWidth);

                kstar0mass->SetBinContent(nfile+1, mass);
                kstar0mass->SetBinError(nfile+1, massError);

                kstar0width->SetBinContent(nfile+1, width);
                Double_t widthError = TMath::Sqrt((GammaDerivative(mass)**2)*fitter->GetCovarianceMatrixElement(1,1) + fitter->GetCovarianceMatrixElement(2,2) + 2.0*GammaDerivative(mass)*fitter->GetCovarianceMatrixElement(1,2));
                kstar0width->SetBinError(nfile+1, widthError);

                kstar0collWidth->SetBinContent(nfile+1, collWidth);
                kstar0collWidth->SetBinError(nfile+1, collWidthError);

                kstar0decWidth->SetBinContent(nfile+1, width - collWidth);
                Double_t decWidthError = TMath::Sqrt((GammaDerivative(mass)**2)*fitter->GetCovarianceMatrixElement(1,1));
                kstar0decWidth->SetBinError(nfile+1, decWidthError);

                if(nfile==4){
                    TCanvas *singlecanvas = new TCanvas("singlecanvas", "singlecanvas", 0,0,600,600);
                    singlecanvas->cd();
                    printf("Got here! \n");
                    histos[i]->Draw("HIST E SAME");

                    fit->SetLineColor(8);
                    fit->SetLineStyle(1);
                    
                    fit->Draw("SAME");
                    if(fitter){
                        printf("sig11: %f, sig12: %f, sig21: %f, sig22: %f GammaDer(0.8): %f GammaDer(0.85): %f GammaDer(0.9): %f\n", TMath::Sqrt(fitter->GetCovarianceMatrixElement(1,1)), fitter->GetCovarianceMatrixElement(2,1), fitter->GetCovarianceMatrixElement(1,2), TMath::Sqrt(fitter->GetCovarianceMatrixElement(2,2)), GammaDerivative(0.8), GammaDerivative(0.85), GammaDerivative(0.9));
                    }
                }
            }
        }
        printf("************************************************************\n");
         
    }
        //integrals.close();
/*
    TH2D *gammaPlot = new TH2D("gammaPlot", "#Gamma_{tot}(M_{0}*);M_{0}*;#Gamma_{coll};#Gamma_{tot}", 100, 0.82, 0.9, 100, 0.0, 0.08);
    for(int im = 0; im<100; im++){
        for(int ig = 0; ig < 100; ig++){
            gammaPlot->SetBinContent(im+1, ig+1, Gamma(((0.9-0.82)/(100.0))*((double)(im)) + 0.82, ((0.08)/100.0)*((double)(ig))));
        }
    }

    TH1D *gammaMassDpnd = gammaPlot->ProjectionX("gammaMassDpnd");
*/
    TCanvas *masscanvas = new TCanvas("masscanvas", "masscanvas", 50,50, 600, 600);
    masscanvas->cd();
    kstar0mass->Draw();
    massline->Draw("SAME");
    masscanvas->Write();

    for(int i=PARTICLE_NUM; i<PARTICLE_NUM+1; i++){
        canvas[i]->Write();
    }
    kstar0mass->Write();
    kstar0collWidth->Write();
    kstar0decWidth->Write();
    kstar0width->Write();
//    gammaPlot->Write();
//    gammaMassDpnd->Write();
}
Ejemplo n.º 4
0
bool leptonic_fitter_algebraic::fit( const TLorentzVector& B, const TH1& BITF, const TF1& Beff, 
				     const TLorentzVector& lep, 
				     double MEX, double MEY, const TF1& dnuPDF )
{
  if( _dbg > 19 ) cout<<"DBG20 Entered leptonic_fitter_algebraic::fit with B mass: "<<B.M()<<", l_m:"<<lep.M()<<", MET: "<<MEX<<" "<<MEY<<endl;
  if( B.M() <= 0 ) throw std::runtime_error( "leptonic_fitter_algebraic was given a b-jet with an illegal (non-positive) mass!"); 
  if( lep.M() < 0 ) throw std::runtime_error( "leptonic_fitter_algebraic was given a lepton with an illegal (negative) mass!"); 
  _converged = _swapped = false;
  _obsB = B;
  _obsL = lep;

  _BITF = &BITF;
  _Beff = &Beff;
  _dnuPDF = dnuPDF;

  _b_m2 = B.M2();

  double lep_b_angle = lep.Angle( B.Vect() );
  double cos_lep_b = TMath::Cos( lep_b_angle );
  double sin_lep_b = TMath::Sin( lep_b_angle );
  double b_p = B.P();
  double b_e = B.E();
  _denom = b_e - cos_lep_b * b_p;
  
  _lep_p = lep.P();
  _x0 = - _W_m2 / ( 2 * _lep_p );
  _y1 = - sin_lep_b * _x0 * b_p / _denom;
  _x1_0 = _x0 * b_e / _denom  -  _y1*_y1 / _x0;
  _Z2_0 = _x0*_x0 - _W_m2 - _y1*_y1;
  if( _dbg > 219 ) cout<<"DBG220 lfa updated lepton with: "<<lv2str( lep )<<" -> x0:"<<_x0<<", y1: "<<_y1<<", x1_0: "<<_x1_0<<", Z2_0: "<<_Z2_0<<endl;

  static double bnums[3];
  bnums[0] = B.X();
  bnums[1] = B.Y();
  bnums[2] = B.Z();
  TMatrixD bXYZ( 3, 1, bnums );
  _R_T = rotation( 2, lep.Phi() ); // R_z^T
  _R_T *= rotation( 1, lep.Theta() - 0.5*TMath::Pi() ); // R_z^T R_y^T
  TMatrixD rotation_vect( _R_T, TMatrixD::kTransposeMult, bXYZ ); // R_y R_z
  double* rotation_array = rotation_vect.GetMatrixArray();
  double phi_x = - TMath::ATan2( rotation_array[2], rotation_array[1] );
  if( _dbg > 99 ) cout<<"DBG100 lfa x rotation vector is:"<<rotation_array[0]<<" "<<rotation_array[1]<<" "<<rotation_array[2]<<" -> phi_x:"<<phi_x<<endl;
  _R_T *= rotation( 0, - phi_x ); // R_z^T R_y^T R_x^T

  // set up _Nu's non-zero elements so that \vec{nu} = Nu \vec{t} for any \vec{t} (since only t's 3nd component is used, and its always 1).
  _Nu[0][2] = MEX;
  _Nu[1][2] = MEY;

  double iVarMET = TMath::Power( TMath::Max( 1., dnuPDF.GetHistogram()->GetRMS() ), -2 );
  _invFlatVar[0][0] = _invFlatVar[1][1] = iVarMET; // set up the chi^2 distance with the right order of magnitude (generalizes to rotated covariance matrix)
  if( _dbg > 209 ) cout<<"DBG210 lfa "<<dnuPDF.GetName()<<" --> iVarMET:"<<iVarMET<<endl;

  // (re)define fit parameter, so all fits start off on an equal footing
  _mini->SetPrintLevel( _minimizer_print_level );
  _mini->Clear();
  _mini->SetFunction( _functor );
  leptonic_fitter_algebraic_object = this; // set the function in the functor pointing back to this object. Doubtfull that all this redirection is needed...
  _mini->SetTolerance( _tolerance );
  bool OK = _mini->SetLimitedVariable( 0, "sB", 1.0, 0.4, 0.1, 6.0 );
  //bool OK = _mini->SetVariable( 0, "sB", 1.0, 0.4 );
  if( ! OK ) {cerr<<"minimizer (@lfa) failed to SetVariable."<<endl; return false;}

  // define 1 sigma in terms of the function
  _mini->SetErrorDef( 0.5 ); // since this is a likelihood fit

  // do the minimization
  OK = _mini->Minimize(); 
  if( _dbg > 19 && ( ! OK || _dbg > 59 ) ) cout<<"DBG INFO: initial fit @lfa returned OK: "<<OK<<", has status: "<<_mini->Status()<<endl;

  _converged = OK; // use status somehow? depends on fitter?

  // read parameters
  const double *xs = _mini->X();
  for( int ip = 0; ip < 1; ++ip ) _params[ ip ] = xs[ ip ];

  // return all intermediate results to the minimum, in particular, the discriminant
  calc_MLL( _params, true );
  TMatrixD nu_vec( _Emat, TMatrixD::kMult, _tvec );
  update_nu_and_decay_chain( nu_vec );
  if( _dbg > 203 ) cout<<"DBG204 lfa finalized _genN: "<<lv2str(_genN)<<", _W: "<<lv2str(_W)<<", & _t: "<<lv2str(_T)<<endl;

  _MLL = _mini->MinValue();
  return true;
} 
Ejemplo n.º 5
0
void residualAlignment(TH2D* residualX, TH2D* residualY, double& offsetX,
                       double& offsetY, double& rotation,
                       double relaxation, bool display)
{
  assert(residualX && residualY && "Processors: can't perform residual alignment without histograms");

  rotation = 0;
  offsetX = 0;
  offsetY = 0;
  double angleWeights = 0;
  double fitChi2 = 0;

  for (int axis = 0; axis < 2; axis++)
  {
    TH2D* hist = 0;
    if (axis) hist = residualX;
    else      hist = residualY;

    // Project the histogram and fit with a gaussian to center the sensor
    TH1D* project = hist->ProjectionX("ResidualProjetion", 1, hist->GetNbinsY());
    project->SetDirectory(0);

    double sigma = project->GetBinWidth(1);
    double mean = 0;
    fitGaussian(project, mean, sigma, false);

    if (axis) offsetX = mean;
    else      offsetY = mean;

    delete project;

    std::vector<double> ptsX;
    std::vector<double> ptsY;
    std::vector<double> ptsErr;

    const unsigned int numSlices = hist->GetNbinsY();

    for (Int_t row = 1; row <= (int)numSlices; row++)
    {
      TH1D* slice = hist->ProjectionX("ResidualSlice", row, row);
      slice->SetDirectory(0);

      double mean = 0;
      double sigma = 0;
      double factor = 0;
      double background = 0;

      if (slice->Integral() < 1) { delete slice; continue; }
      fitGaussian(slice, mean, sigma, factor, background, false);

      const double sliceMin = slice->GetBinCenter(1);
      const double sliceMax = slice->GetBinCenter(slice->GetNbinsX());
      delete slice;

      // Quality assurance

      // Sigma is contained in the slice's range
      if (sigma > (sliceMax - sliceMin)) continue;
      // Mean is contained in the slice's range
      if (mean > sliceMax || mean < sliceMin) continue;
      // Peak is contains sufficient events
      if (factor < 100) continue;
      // Sufficient signal to noise ratio
      if (factor / background < 10) continue;

      // Get the total number of events in the gaussian 1 sigma
      Int_t sigRangeLow = hist->FindBin(mean - sigma);
      Int_t sigRangeHigh = hist->FindBin(mean + sigma);

      double sigRangeTotal = 0;
      for (Int_t bin = sigRangeLow; bin <= sigRangeHigh; bin++)
        sigRangeTotal += hist->GetBinContent(bin);

      // 2 * 1 sigma integral shoudl give ~ area under gaussian
      sigma /= sqrt(2 * sigRangeTotal);

      ptsX.push_back(hist->GetYaxis()->GetBinCenter(row));
      ptsY.push_back(mean);
      ptsErr.push_back(sigma);
    }

    if (ptsX.size() < 3) continue;

    std::vector<double> yvals = ptsY;
    std::sort(yvals.begin(), yvals.end());
    const double median = yvals[yvals.size()/2];
    double avgDeviation = 0;
    for (unsigned int i = 0; i < yvals.size(); i++)
      avgDeviation += fabs(yvals[i] - median);
    avgDeviation /= (double)yvals.size();

    std::vector<double> ptsXGood;
    std::vector<double> ptsYGood;
    std::vector<double> ptsErrGood;

    for (unsigned int i = 0; i < ptsX.size(); i++)
    {
      if (fabs(ptsY[i] - median) > 1.5*avgDeviation) continue;
      ptsXGood.push_back(ptsX[i]);
      ptsYGood.push_back(ptsY[i]);
      ptsErrGood.push_back(ptsErr[i]);
    }

    if (ptsXGood.size() < 3) continue;

    TGraphErrors* graph = new TGraphErrors(ptsXGood.size(),
                                           &(ptsXGood.at(0)),
                                           &(ptsYGood.at(0)), 0,
                                           &(ptsErrGood.at(0)));

    TF1* fitFunc = new TF1("f1", "1 ++ x");
    TF1* result = 0;

    graph->Fit(fitFunc, "Q0E").Get();
    result = graph->GetFunction(fitFunc->GetName());

    // Weight the angle by the slope uncertainty and the inverse of the chi2 normalized
    double weight = result->GetParError(1);
    const double chi2 = result->GetChisquare() / (double)result->GetNDF();
    fitChi2 += chi2;
    weight *= chi2;
    if (weight > 10 * DBL_MIN) weight = 1.0 / weight;
    else weight = 1.0;

    if (axis)
    {
      rotation -= weight * atan(result->GetParameter(1));
      offsetX = result->GetParameter(0);
    }
    else
    {
      rotation += weight * atan(result->GetParameter(1));
      offsetY = result->GetParameter(0);
    }

    angleWeights += weight;

    if (display)
    {
      TCanvas* can = new TCanvas("ResidualAlignment", "Residual Alignment", 900, 600);
      can->Divide(2);
      can->cd(1);
      hist->Draw("COLZ");
      can->cd(2);
      result->SetLineColor(46);
      result->SetLineWidth(2);
      graph->Draw("ap");
      result->Draw("SAME");
      can->Update();
      can->WaitPrimitive();
    }

    delete fitFunc;
    delete graph;
  }

  if (angleWeights > 10 * DBL_MIN)
    rotation /= angleWeights;
  std::cout << "relaxation: " << relaxation << std::endl;
  rotation *= relaxation;
  offsetX *= relaxation;
  offsetY *= relaxation;
}
Ejemplo n.º 6
0
// Soft radiation corrections for L3Res
void softrad(double etamin=0.0, double etamax=1.3, bool dodijet=false) {

  setTDRStyle();
  writeExtraText = false; // for JEC paper CWR

  TDirectory *curdir = gDirectory;

  // Open jecdata.root produced by reprocess.C
  TFile *fin = new TFile("rootfiles/jecdata.root","UPDATE");
  assert(fin && !fin->IsZombie());
  
  const int ntypes = 3;
  const char* types[ntypes] = {"data", "mc", "ratio"};
  const int nmethods = 2;
  const char* methods[nmethods] = {"mpfchs1", "ptchs"};
  const int nsamples = (dodijet ? 4 : 3);
  const char* samples[4] = {"gamjet", "zeejet", "zmmjet", "dijet"};
  string sbin = Form("eta%02.0f-%02.0f",10*etamin,10*etamax);
  const char* bin = sbin.c_str();
  const int nalphas = 4;
  const int alphas[nalphas] = {30, 20, 15, 10};

  // Z+jet bins
  const double ptbins1[] = {30, 40, 50, 60, 75, 95, 125, 180, 300, 1000};
  const int npt1 = sizeof(ptbins1)/sizeof(ptbins1[0])-1;
  TH1D *hpt1 = new TH1D("hpt1","",npt1,&ptbins1[0]);
  TProfile *ppt1 = new TProfile("ppt1","",npt1,&ptbins1[0]);

  // gamma+jet bins
  const double ptbins2[] = {30, 40, 50, 60, 75, 100, 125, 155, 180,
			    210, 250, 300, 350, 400, 500, 600, 800};
  const int npt2 = sizeof(ptbins2)/sizeof(ptbins2[0])-1;
  TH1D *hpt2 = new TH1D("hpt2","",npt2,&ptbins2[0]);
  TProfile *ppt2 = new TProfile("ppt2","",npt2,&ptbins2[0]);

  // dijet bins
  const double ptbins4[] = {20, 62, 107, 175, 242, 310, 379, 467,
			    628, 839, 1121, 1497, 2000};
  const int npt4 = sizeof(ptbins4)/sizeof(ptbins4[0])-1;
  TH1D *hpt4 = new TH1D("hpt4","",npt4,&ptbins4[0]);
  TProfile *ppt4 = new TProfile("ppt4","",npt4,&ptbins4[0]);

  TLatex *tex = new TLatex();
  tex->SetNDC();
  tex->SetTextSize(0.045);

  map<string,const char*> texlabel;
  texlabel["gamjet"] = "#gamma+jet";
  texlabel["zeejet"] = "Z#rightarrowee+jet";
  texlabel["zmmjet"] = "Z#rightarrow#mu#mu+jet";
  texlabel["dijet"] = "Dijet";
  texlabel["ptchs"] = "p_{T} balance (CHS)";
  texlabel["mpfchs"] = "MPF raw (CHS)";
  texlabel["mpfchs1"] = "MPF type-I (CHS)";

  // overlay of various alpha values
  TCanvas *c1 = new TCanvas("c1","c1",ntypes*400,nmethods*400);
  c1->Divide(ntypes,nmethods);

  TH1D *h1 = new TH1D("h1",";p_{T} (GeV);Response",1270,30,1300);

  // extrapolation vs alpha for each pT bin
  vector<TCanvas*> c2s(ntypes*nmethods);
  for (unsigned int icanvas = 0; icanvas != c2s.size(); ++icanvas) {
    TCanvas *c2 = new TCanvas(Form("c2_%d",icanvas),Form("c2_%d",icanvas),
			      1200,1200);
    c2->Divide(3,3);
    c2s[icanvas] = c2;
  }

  TH1D *h2 = new TH1D("h2",";#alpha;Response",10,0.,0.4);
  h2->SetMaximum(1.08);
  h2->SetMinimum(0.88);

  // krad corrections
  TCanvas *c3 = new TCanvas("c3","c3",ntypes*400,nmethods*400);
  c3->Divide(ntypes,nmethods);

  TH1D *h3 = new TH1D("h3",";p_{T,ref} (GeV);FSR sensitivity: -dR/d#alpha [%]",
		      1270,30,1300);

  cout << "Reading in data" << endl << flush;
  // Read in plots vs pT (and alpha)
  map<string, map<string, map<string, map<int, TGraphErrors*> > > > gemap;
  map<string, map<string, map<string, map<int, TGraphErrors*> > > > gamap;
  for (int itype = 0; itype != ntypes; ++itype) {
    for (int  imethod = 0; imethod != nmethods; ++imethod) {
      for (int  isample = 0; isample != nsamples; ++isample) {

	for (int  ialpha = 0; ialpha != nalphas; ++ialpha) {

	  fin->cd();
	  assert(gDirectory->cd(types[itype]));
	  assert(gDirectory->cd(bin));
	  TDirectory *d = gDirectory;

	  const char *ct = types[itype];
	  const char *cm = methods[imethod];
	  const char *cs = samples[isample];
	  const int a = alphas[ialpha];
	  // Get graph made vs pT
	  string s = Form("%s/%s/%s_%s_a%d",types[itype],bin,cm,cs,a);
	  TGraphErrors *g = (TGraphErrors*)fin->Get(s.c_str());
	  if (!g) cout << "Missing " << s << endl << flush;
	  assert(g);

	  // Clean out empty points
	  // as well as trigger-biased ones for dijets
	  // as well as weird gamma+jet high pT point
	  for (int i = g->GetN()-1; i != -1; --i) {
	    if (g->GetY()[i]==0 || g->GetEY()[i]==0 ||
		(string(cs)=="dijet" && g->GetX()[i]<70.) ||
		(string(cs)=="gamjet" && g->GetX()[i]>600. && etamin!=0))
	      g->RemovePoint(i);
	  }

	  gemap[ct][cm][cs][a] = g;
	  
	  // Sort points into new graphs vs alpha
	  TH1D *hpt = (isample==0 ? hpt2 : hpt1);
	  TProfile *ppt = (isample==0 ? ppt2 : ppt1);
	  if (isample==3) { hpt = hpt4; ppt = ppt4; } // pas-v6
	  for (int i = 0; i != g->GetN(); ++i) {
	    
	    double pt = g->GetX()[i];
	    ppt->Fill(pt, pt);
	    int ipt = int(hpt->GetBinLowEdge(hpt->FindBin(pt))+0.5);
	    //int ipt = int(pt+0.5);
	    TGraphErrors *ga = gamap[ct][cm][cs][ipt];
	    if (!ga) {
	      ga = new TGraphErrors(0);
	      ga->SetMarkerStyle(g->GetMarkerStyle());
	      ga->SetMarkerColor(g->GetMarkerColor());
	      ga->SetLineColor(g->GetLineColor());
	      gamap[ct][cm][cs][ipt] = ga;
	    }
	    int n = ga->GetN();
	    ga->SetPoint(n, 0.01*a, g->GetY()[i]);
	    ga->SetPointError(n, 0, g->GetEY()[i]);
	  } // for i 

	} // for ialpha

      } // for isample
    } // for imethod
  } // for itype

  cout << "Drawing plots vs pT for each alpha" << endl << flush;

  // 2x6 plots
  for (int itype = 0; itype != ntypes; ++itype) {
    for (int  imethod = 0; imethod != nmethods; ++imethod) {

      const char *ct = types[itype];
      const char *cm = methods[imethod];

      int ipad = ntypes*imethod + itype + 1; assert(ipad<=6);
      c1->cd(ipad);
      gPad->SetLogx();
      h1->SetMaximum(itype<2 ? 1.15 : 1.08);
      h1->SetMinimum(itype<2 ? 0.85 : 0.93);
      h1->SetYTitle(Form("Response (%s)",ct));
      h1->DrawClone("AXIS");
      tex->DrawLatex(0.20,0.85,texlabel[cm]);
      tex->DrawLatex(0.20,0.80,"|#eta| < 1.3, #alpha=0.1--0.3");
      TLegend *leg = tdrLeg(0.60,0.75,0.90,0.90);

      for (int  isample = 0; isample != nsamples; ++isample) {
	for (int  ialpha = 0; ialpha != nalphas; ++ialpha) {

	  const char *cs = samples[isample];
	  const int a = alphas[ialpha];
	  TGraphErrors *g = gemap[ct][cm][cs][a]; assert(g);

	  // Clean out points with very large uncertainty for plot readability
	  for (int i = g->GetN()-1; i != -1; --i) {
	    if (g->GetEY()[i]>0.02) g->RemovePoint(i);
	  }

	  g->Draw("SAME Pz");

	  if (ialpha==0) leg->AddEntry(g,texlabel[cs],"P");
	}
      } // for isample

      // Individual plots for JEC paper
      if ( true ) { // paper

	TH1D *h = new TH1D(Form("h_5%s_%s",ct,cm),
			   Form(";p_{T} (GeV);Response (%s)",ct),
			   1270,30,1300);
	h->GetXaxis()->SetMoreLogLabels();
	h->GetXaxis()->SetNoExponent();
	h->SetMinimum(0.88);
	h->SetMaximum(1.13);

	writeExtraText = true;
	extraText = (string(ct)=="mc" ? "Simulation" : "");
	lumi_8TeV = (string(ct)=="mc" ? "" : "19.7 fb^{-1}");
	TCanvas *c0 = tdrCanvas(Form("c0_%s_%s",cm,ct), h, 2, 11, true);
	c0->SetLogx();
	

	TLegend *leg = tdrLeg(0.55,0.68,0.85,0.83);
	tex->DrawLatex(0.55,0.85,texlabel[cm]);
	tex->DrawLatex(0.55,0.18,"|#eta| < 1.3, #alpha=0.3");
	//tex->DrawLatex(0.55,0.18,"Anti-k_{T} R=0.5");

	// Loop over Z+jet and gamma+jet (only, no dijet/multijet)
	for (int  isample = 0; isample != min(3,nsamples); ++isample) {
	  
	  const char *cs = samples[isample];
	  TGraphErrors *g = gemap[ct][cm][cs][30]; assert(g);
	  g->Draw("SAME Pz");
	  
	  leg->AddEntry(g,texlabel[cs],"P");
	} // for isample

	if (etamin==0) {
	  c0->SaveAs(Form("pdf/paper_softrad_%s_%s_vspt.pdf",ct,cm));
	  c0->SaveAs(Form("pdfC/paper_softrad_%s_%s_vspt.C",ct,cm));
	}
	else {
	  c0->SaveAs(Form("pdf/an_softrad_%s_%s_eta%1.0f-%1.0f_vspt.pdf",
			  ct,cm,10*etamin,10*etamax));
	}
      } // paper

    } // for imethod
  } // for itype
  
  c1->cd(0);
  //cmsPrel(_lumi, true);
  CMS_lumi(c1, 2, 33);
  c1->SaveAs("pdf/softrad_2x6_vspt.pdf");


  cout << "Drawing plots vs alpha for each pT" << endl << flush;
  cout << "...and fitting slope vs alpha" << endl << flush;

  map<string, map<string, map<string, TGraphErrors* > > > gkmap;

  // 2x6 plots
  for (int itype = 0; itype != ntypes; ++itype) {
    for (int  imethod = 0; imethod != nmethods; ++imethod) {
      
      int icanvas = nmethods*imethod + itype; assert(icanvas<=6);
      TCanvas *c2 = c2s[icanvas]; assert(c2);

      const char *ct = types[itype];
      const char *cm = methods[imethod];

      const int npads = 9;
      for (int ipad = 0; ipad != npads; ++ipad) {
	c2->cd(ipad+1);
	h2->SetYTitle(Form("Response (%s)",ct));
	h2->DrawClone("AXIS");
	tex->DrawLatex(0.20,0.85,texlabel[cm]);
	tex->DrawLatex(0.20,0.80,"|#eta| < 1.3");
	tex->DrawLatex(0.20,0.75,Form("%1.0f < p_{T} < %1.0f GeV",
				      hpt1->GetBinLowEdge(ipad+1),
				      hpt1->GetBinLowEdge(ipad+2)));
	TLegend *leg = tdrLeg(0.65,0.75,0.90,0.90);
	leg->AddEntry(gemap[ct][cm]["gamjet"][30], texlabel["gamjet"], "P");
	leg->AddEntry(gemap[ct][cm]["zeejet"][30], texlabel["zeejet"], "P");
	leg->AddEntry(gemap[ct][cm]["zmmjet"][30], texlabel["zmmjet"], "P");
	leg->AddEntry(gemap[ct][cm]["dijet"][30], texlabel["dijet"], "P");
      }

      for (int  isample = 0; isample != nsamples; ++isample) {

	const char *cs = samples[isample];

	map<int, TGraphErrors*> &gam = gamap[ct][cm][cs];
	map<int, TGraphErrors*>::iterator itpt;
	for (itpt = gam.begin(); itpt != gam.end(); ++itpt) {

	  int ipt = itpt->first;
	  int jpt = hpt1->FindBin(ipt);
	  if (jpt>npads) continue;
	  assert(jpt<=npads);
	  c2->cd(jpt);
	  
	  TGraphErrors *ga = itpt->second; assert(ga);
	  
	  ga->Draw("SAME Pz");

	  // Fit slope
	  TF1 *f1 = new TF1(Form("f1_%s_%s_%s_%d",ct,cm,cs,ipt),
			    "(x<1)*([0]+[1]*x) + (x>1 && x<2)*[0] +"
			    "(x>2)*[1]",-1,1);
	  f1->SetLineColor(ga->GetLineColor());
	  f1->SetParameters(1,0);
	  const double minalpha = (isample==0 ? 10./ipt : 5./ipt);
	  // Constrain slope to within reasonable values
	  // in the absence of sufficient data using priors
	  if (true) { // use priors
	    int n = ga->GetN();
	    // For response, limit to 1+/-0.02 (we've corrected for L3Res
	    ga->SetPoint(n, 1.5, 1);
	    ga->SetPointError(n, 0, 0.02);
	    n = ga->GetN();
	    if (imethod==1) { // pT balance
	      // For pT balance, estimate slope of <vecpT2>/alpha from data
	      // => 7.5%/0.30 = 25%
	      // Approximate uncertainty on this to be
	      // 0.5%/0.30 ~ 1.5% for data, 0.5%/0.30 ~ 1.5% for Z+jet MC, and
	      // 2%/0.30 ~ 6% for gamma+jet MC (same as slope)
	      if (itype==0)               ga->SetPoint(n, 2.5, -0.250); // DT
	      if (itype==1 && isample!=0) ga->SetPoint(n, 2.5, -0.250); // MC
	      if (itype==1 && isample==0) ga->SetPoint(n, 2.5, -0.190);
	      if (itype==2 && isample!=0) ga->SetPoint(n, 2.5, -0.000); // rt
	      if (itype==2 && isample==0) ga->SetPoint(n, 2.5, -0.060); 
	      //
	      // BUG: found 2015-01-08 (no effect on ratio)
	      //if (itype==1)               ga->SetPointError(n, 0, -0.015);
	      if (itype==0)               ga->SetPointError(n, 0, -0.015); // DT
	      if (itype==1 && isample!=0) ga->SetPointError(n, 0, -0.015); // MC
	      if (itype==1 && isample==0) ga->SetPointError(n, 0, -0.060);
	      if (itype==2 && isample!=0) ga->SetPointError(n, 0, -0.015); // rt
	      if (itype==2 && isample==0) ga->SetPointError(n, 0, -0.060); 
	    }
	    if (imethod==0) { // MPF
	      // For MPF, expectation is no slope
	      // Maximal slope would be approximately
	      // (<vecpT2>/alpha ~ 25% from pT balance) times
	      // (response difference between pT1 and vecpT2~10%)
	      // => 0.25*0.10 = 2.5%
	      // For data/MC, estimate uncertainty as half of this
	      // => 1.25%
	      ga->SetPoint(n, 2.5, 0.);
	      if (itype!=2) ga->SetPointError(n, 0, 0.025);
	      if (itype==2) ga->SetPointError(n, 0, 0.0125);
	    } // MPF
	  } // use priors

	  if (ga->GetN()>2) {

	    f1->SetRange(minalpha, 3.);
	    ga->Fit(f1,"QRN");

	    if (f1->GetNDF()>=0) {
	      f1->DrawClone("SAME");
	      f1->SetRange(0,0.4);
	      f1->SetLineStyle(kDashed);
	      f1->DrawClone("SAME");

	      // Store results
	      TGraphErrors *gk = gkmap[ct][cm][cs];
	      if (!gk) {
		gk = new TGraphErrors(0);
		gk->SetMarkerStyle(ga->GetMarkerStyle());
		gk->SetMarkerColor(ga->GetMarkerColor());
		gk->SetLineColor(ga->GetLineColor());
		gkmap[ct][cm][cs] = gk;
	      }
	      int n = gk->GetN();
	      TProfile *ppt = (isample==0 ? ppt2 : ppt1);
	      if (isample==3) { ppt = ppt4; } // pas-v6
	      double pt = ppt->GetBinContent(ppt->FindBin(ipt));
	      gk->SetPoint(n, pt, f1->GetParameter(1));
	      gk->SetPointError(n, 0, f1->GetParError(1));
	    } // f1->GetNDF()>=0
	  } // ga->GetN()>2
	} // for itpt
	
      } // for isample
      
      c2->SaveAs(Form("pdf/softrad_3x3_%s_%s_vsalpha.pdf",ct,cm));
      
    }
  }


  cout << "Drawing plots of kFSR vs pT" << endl;

  // 2x6 plots
  for (int itype = 0; itype != ntypes; ++itype) {
    for (int  imethod = 0; imethod != nmethods; ++imethod) {

      const char *ct = types[itype];
      const char *cm = methods[imethod];

      TMultiGraph *mgk = new TMultiGraph();

      int ipad = ntypes*imethod + itype + 1; assert(ipad<=6);
      c3->cd(ipad);
      gPad->SetLogx();
      h3->SetMaximum(imethod==0 ? 0.05 : (itype!=2 ? 0.1 : 0.25));
      h3->SetMinimum(imethod==0 ? -0.05 : (itype!=2 ? -0.4 : -0.25));
      h3->SetYTitle(Form("k_{FSR} = dR/d#alpha (%s)",ct));
      h3->DrawClone("AXIS");
      tex->DrawLatex(0.20,0.85,texlabel[cm]);
      tex->DrawLatex(0.20,0.80,"|#eta| < 1.3");
      TLegend *leg = tdrLeg(0.60,0.75,0.90,0.90);

      for (int  isample = 0; isample != nsamples; ++isample) {

	const char *cs = samples[isample];
	TGraphErrors *gk = gkmap[ct][cm][cs]; assert(gk);
	
	leg->AddEntry(gk,texlabel[cs],"P");

	// Fit each sample separately for pT balance
	if (true) {

	  TF1 *fk = new TF1(Form("fk_%s_%s_%s",ct,cm,cs),
			    "[0]+[1]*log(0.01*x)+[2]*pow(log(0.01*x),2)",
			    30,1300);
	  fk->SetParameters(-0.25,-0.5);
	  fk->SetLineColor(gk->GetLineColor());
	  gk->Fit(fk, "QRN");

	  tex->SetTextColor(fk->GetLineColor());
	  tex->DrawLatex(0.55,0.27-0.045*isample,
			 Form("#chi^{2}/NDF = %1.1f / %d",
			      fk->GetChisquare(), fk->GetNDF()));
	  tex->SetTextColor(kBlack);

	  // Error band
	  const int n = fk->GetNpar();
	  TMatrixD emat(n,n);
	  gMinuit->mnemat(emat.GetMatrixArray(), n);
	  TF1 *fke = new TF1(Form("fk_%s_%s_%s",ct,cm,cs),
			     sr_fitError, 30, 1300, 1);
	  _sr_fitError_func = fk;
	  _sr_fitError_emat = &emat;

	  fke->SetLineStyle(kSolid);
	  fke->SetLineColor(fk->GetLineColor()-10);
	  fke->SetParameter(0,-1);
	  fke->DrawClone("SAME");
	  fke->SetParameter(0,+1);
	  fke->DrawClone("SAME");

	  fk->DrawClone("SAME");
	  gk->DrawClone("SAME Pz");

	  // Store soft radiation corrections in fsr subdirectory
	  assert(fin->cd(ct));
	  assert(gDirectory->cd(bin));
	  if (!gDirectory->FindObject("fsr")) gDirectory->mkdir("fsr");
	  assert(gDirectory->cd("fsr"));

	  TH1D *hk = (TH1D*)(isample==0 ? hpt2->Clone() : hpt1->Clone());
	  hk->SetName(Form("hkfsr_%s_%s",cm,cs));
	  TProfile *ppt = (isample==0 ? ppt2 : ppt1);
	  if (isample==3) { ppt = ppt4; } // pas-v6
	  for (int i = 1; i != hk->GetNbinsX()+1; ++i) {
	    double pt = ppt->GetBinContent(i);
	    if (pt>30 && pt<1300) {
	      hk->SetBinContent(i, fk->Eval(pt));
	      hk->SetBinError(i, fabs(fke->Eval(pt)-fk->Eval(pt)));
	    }
	    else {
	      hk->SetBinContent(i, 0);
	      hk->SetBinError(i, 0);
	    }
	  }
	  
	  hk->Write(hk->GetName(), TObject::kOverwrite);

	  // Factorize error matrix into eigenvectors
	  // Remember: A = Q*Lambda*Q^-1, where
	  // A is emat, Q is eigmat, and Lambda is a diagonal matrix with
	  // eigenvalues from eigvec on the diagonal. For eigenmatrix
	  // Q^-1 = Q^T, i.e. inverse matrix is the original transposed
	  TVectorD eigvec(n);
	  TMatrixD eigmat = emat.EigenVectors(eigvec);

	  // Eigenvectors are the columns and sum of eigenvectors squared
	  // equals original uncertainty. Calculate histograms from the
	  // eigenvectors and store them
	  TF1 *fkeig = (TF1*)fk->Clone(Form("%s_eig",fk->GetName()));
	  fkeig->SetLineStyle(kDotted);
	  for (int ieig = 0; ieig != n; ++ieig) {

	    // Eigenvector functions
	    for (int i = 0; i != n; ++i) {
	      fkeig->SetParameter(i, fk->GetParameter(i)
				  + eigmat[i][ieig] * sqrt(eigvec[ieig]));
	    }
	    fkeig->DrawClone("SAMEL");

	    // Eigenvector histograms evaluated at bin mean pT
	    TH1D *hke = (TH1D*)hk->Clone(Form("%s_eig%d",hk->GetName(),ieig));
	    hke->Reset();

	    for (int i = 0; i != gk->GetN(); ++i) {

	      double pt = gk->GetX()[i];
	      int ipt = hke->FindBin(pt);
	      // Need to store central value as well, because
	      // uncertainty sources are signed
	      hke->SetBinContent(ipt, fkeig->Eval(pt)-fk->Eval(pt));
	      hke->SetBinError(ipt, fabs(fkeig->Eval(pt)-fk->Eval(pt)));
	    }
	    hke->Write(hke->GetName(), TObject::kOverwrite);
	  }

	  cout << "." << flush;
	} // if tree
      } // for isample
    } // for imethod
  } // for itype
  
  c3->cd(0);
  //cmsPrel(_lumi, true);
  CMS_lumi(c3, 2, 33);
  c3->SaveAs("pdf/softrad_2x6_kfsr.pdf");

  fin->Close();
  curdir->cd();
} // softrad