int main(){
  std::vector<MCSample> Samples;
  PkPhi.FileName="../PkphiSingle.root";
  PkPhi.Description="#Lambda_b -> p K #phi background";
  Samples.push_back(PkPhi);
  Rare.FileName="../RareMCSingle.root";
  Rare.Description="#eta' -> #pi #pi #gamma";
  Samples.push_back(Rare);
  Rare2.FileName="../Rare2MCSingle.root";
  Rare2.Description="#eta' -> #pi #pi #eta";
  Samples.push_back(Rare2);
  Control.FileName="../CCMCSingle.root";
  Control.Description="Control Channel";
  Samples.push_back(Control);
  
  for(auto &Sample : Samples){
    TreeReader * Reader = new TreeReader("DecayTree");
    Reader->AddFile(Sample.FileName.data());
    Reader->Initialize();
    Long64_t N=Reader->GetEntries();
    Sample.CC=new CorrelationCoeff(Sample.Description);
    std::string HeadMassName="Lambda_b0_DTF_MF";
    Reader->GetEntry(0);
    try{
      Reader->GetValue("Lambda_b0_DTF_MF");
    }catch(...){
      HeadMassName="Bu_DTF_MF";
    }
    for(int i=0;i<N;++i){
      Reader->GetEntry(i);
      double HeadMass=Reader->GetValue(HeadMassName.data());
      double EtaMass=Reader->GetValue("eta_prime_MM");
      if(HeadMassName.compare("Lambda_b0_DTF_MF")==0){
	if(HeadMass>5200.0&&HeadMass<6000.0&&EtaMass>880.0&&EtaMass<1040.0){
	  Sample.CC->Fill(HeadMass,EtaMass);
	}
      }else{
	if(HeadMass>5000.0&&HeadMass<5500.0&&EtaMass>880.0&&EtaMass<1040.0){
	  Sample.CC->Fill(HeadMass,EtaMass);
	}
      }
    }
    double NBootStraps=N*10;
    std::cout<<"After "<<NBootStraps<<" Boostraps"<<std::endl;
    std::cout<<Sample.Description<<" Coefficient = "<<Sample.CC->GetCC()<<" +/- "<<Sample.CC->GetBootstrapError(NBootStraps)<<std::endl;
  }
  TFile * Output = new TFile("Output.root","RECREATE");
  for(auto &Sample : Samples){
    Sample.CC->GetBootStrapHist(0)->Write();
    Sample.CC->GetCorrelationPlot()->Write();
  }
    
    

}
int main(int argc, char **argv)
{
	TString analysis = "Lb2Lmumu";
	bool MC = false;
	TString base = "/afs/cern.ch/work/p/pluca/weighted/Lmumu/";

	if(argc > 1)
	{
		string arg = argv[1];
		if(arg == "MC") MC = true;
	}

	vector< string > novar;
	novar.push_back("Lb_MassCons");
	novar.push_back("Lb_MassConsLambda");
	novar.push_back("Lb_MassConsJpsiLambda");
	novar.push_back("cosTheta");
	novar.push_back("cosThetaL");
	novar.push_back("cosThetaB");
	novar.push_back("phiL");
	novar.push_back("phiB");
	novar.push_back("dphi");
	novar.push_back("cosTheta_TRUE");
	novar.push_back("cosThetaL_TRUE");
	novar.push_back("cosThetaB_TRUE");
	novar.push_back("phiL_TRUE");
	novar.push_back("phiB_TRUE");
	novar.push_back("dphi_TRUE");

	TCut cutJpsi = CutsDef::cutJpsi;
	TCut cutMuMu = CutsDef::cutMuMu_veto;

	TreeReader* treeReader = new TreeReader("tree");

	TString namefile = base + "candLb";
	if(MC) namefile += "_MC";
	namefile += ".root";

	TFile * candFile = new TFile(namefile,"recreate");

	if(!MC) treeReader->AddFile(base+analysis+"_CL_NBweighted.root");
	else treeReader->AddFile(base+analysis+"_MC_Pythia8_NBweighted.root");
	treeReader->Initialize(novar,"except");

	Analysis * anaLbMuMu = new Analysis("Lb2Lmumu","Lb",treeReader,&cutMuMu);

	candFile->cd();
	TTree * candLbMuMu = anaLbMuMu->applyCuts(&addVariables);
	candLbMuMu->Write();
	string tnameMuMu = candLbMuMu->GetName();

	candFile->Close();
	candFile = TFile::Open(namefile,"update");
	TTree * singleCand_LbMuMu = anaLbMuMu->checkMultiple("weight",namefile,tnameMuMu,&randomKill);
	singleCand_LbMuMu->Write();



	if(MC)
	{
		treeReader = new TreeReader("tree");
		treeReader->AddFile(base+"Lb2JpsiL_MC_Pythia8_NBweighted.root");
		treeReader->Initialize(novar,"except");
	}
	Analysis * anaLbJpsi = new Analysis("Lb2JpsiL","Lb",treeReader,&cutJpsi);

	candFile->cd();
	TTree * candLbJpsi = anaLbJpsi->applyCuts(&addVariables);
	candLbJpsi->Write();
	string tnameJpsi = candLbJpsi->GetName();

	candFile->Close();
	candFile = TFile::Open(namefile,"update");	
	TTree * singleCand_LbJpsi = anaLbJpsi->checkMultiple("weight",namefile,tnameJpsi,&randomKill);
	singleCand_LbJpsi->Write();

	candFile->cd();
	TTree * candLbJpsi_reduced = anaLbJpsi->applyCuts(&addVariables,300);
	candLbJpsi_reduced->SetName("candLb2JpsiL_reduced");
	candLbJpsi_reduced->Write();



	if(MC)
	{
		candFile->cd();
		TCut jpsiSwap = cutJpsi + CutsDef::jpsiSwapID;
		TCut mumuSwap = cutMuMu + CutsDef::mumuSwapID;
		TTree * mumuSwapTree = anaLbMuMu->applyCuts(&mumuSwap, false,&addVariables);
		mumuSwapTree->SetName("candLmumuSwap");
		mumuSwapTree->Write();
		TTree * jpsiSwapTree = anaLbJpsi->applyCuts(&jpsiSwap, false, &addVariables);
		jpsiSwapTree->SetName("candJpsiLSwap");
		jpsiSwapTree->Write();

		TreeReader * KSReader = new TreeReader("tree");
		KSReader->AddFile(base+"Bd2JpsiKS_MC12_NBweighted.root");
		KSReader->Initialize(novar,"except");
		TCut cutBdLL = cutJpsi + CutsDef::LLcut;
		TCut cutBdDD = cutJpsi + CutsDef::DDcut;
		Analysis * KSAnalysis_LL = new Analysis("BdJpsiKS_LL","B0",KSReader,&cutBdLL);
		TTree *KSTree_LL = KSAnalysis_LL->applyCuts(&addVariables);		
		KSTree_LL->Write();
		Analysis * KSAnalysis_DD = new Analysis("BdJpsiKS_DD","B0",KSReader,&cutBdDD);
		TTree *KSTree_DD = KSAnalysis_DD->applyCuts(&addVariables);		
		KSTree_DD->Write();
		Analysis * KSAnalysis_all = new Analysis("BdJpsiKS","B0",KSReader,&cutJpsi);
		TTree *KSTree = KSAnalysis_all->applyCuts(&addVariables);		
		KSTree->Write();

		candFile->cd();
		TreeReader * KstmumuReader = new TreeReader("tree");
		KstmumuReader->AddFile(base+"Bu2Kstmumu_MC12_NBweighted.root");
		KstmumuReader->Initialize(novar,"except");
		Analysis * KstmumuAnalysis = new Analysis("BuKstmumu","B0",KstmumuReader,&cutMuMu);
		TTree *KstmumuTree = KstmumuAnalysis->applyCuts(&addVariables);
		KstmumuTree->Write();

		candFile->cd();
		TreeReader * KSmumuReader = new TreeReader("tree");
		KSmumuReader->AddFile(base+"Bd2KSmumu_MC12_NBweighted.root");
		KSmumuReader->Initialize(novar,"except");
		Analysis * KSmumuAnalysis = new Analysis("BdKSmumu","B0",KSmumuReader,&cutMuMu);
		TTree *KSmumuTree = KSmumuAnalysis->applyCuts(&addVariables);
		KSmumuTree->Write();

		candFile->cd();
		TreeReader * JpsiGenReader = new TreeReader("tree");
		JpsiGenReader->AddFile("/afs/cern.ch/work/k/kreps/public/LbLMuMuAna/generatorLevel/LbJpsiLGenOnlyDaughInAccForRadiativeTail.root");
		JpsiGenReader->Initialize();
		TCut JpsiTailCut = "TMath::Power(J_psi_1S_MASS/1000,2) < 8 && Lb_MASS > 5300 && Lambda0_MASS > 1105 && Lambda0_MASS < 1125";
		Analysis * JpsiTailAnalysis = new Analysis("JpsiTail","Lb",JpsiGenReader,&JpsiTailCut);
		TTree *JpsiTailTree = JpsiTailAnalysis->applyCuts(&RenameMass, 0.1);
		JpsiTailTree->Write();
	}

	candFile->Close();
	delete candFile;

	return 0;
}
int main() {
    bool recutdata=false;
    bool recutmc=false;
    bool remakedatasets=false;
    std::vector<std::string> VariablesToCompare= {"gamma_CL","nSPDHits","Bu_DIRA_OWNPV","Bu_M01"};
    auto BranchesToKeepMC = ControlCuts::BranchesToKeep;
    for(auto branch : VariablesToCompare) {
        if (std::find(BranchesToKeepMC.begin(),BranchesToKeepMC.end(),branch)==std::end(BranchesToKeepMC)) {
            BranchesToKeepMC.push_back(std::move(branch));
        }
    }

    auto BranchesToKeep = ControlCuts::BranchesToKeep;
    for(auto branch : VariablesToCompare) {
        if (std::find(BranchesToKeep.begin(),BranchesToKeep.end(),branch)==std::end(BranchesToKeep)) {
            BranchesToKeep.push_back(std::move(branch));
        }
    }

    if(recutdata) {
        DataFile TwelA(std::getenv("BUKETAPDATAROOT"),Data,Twel,MagAll,buketap,"TriggerCut_SampleA");
        DataFile TwelB(std::getenv("BUKETAPDATAROOT"),Data,Twel,MagAll,buketap,"TriggerCut_SampleB");
        DataFile ElevA(std::getenv("BUKETAPDATAROOT"),Data,Elev,MagAll,buketap,"TriggerCut_SampleA");
        DataFile ElevB(std::getenv("BUKETAPDATAROOT"),Data,Elev,MagAll,buketap,"TriggerCut_SampleB");

        TreeReader* TwelReader = new TreeReader("DecayTree");
        TwelReader->AddFile(TwelA);
        TwelReader->AddFile(TwelB);

        TreeReader* ElevReader = new TreeReader("DecayTree");
        ElevReader->AddFile(ElevA);
        ElevReader->AddFile(ElevB);


        TwelReader->Initialize(BranchesToKeep,"names");
        ElevReader->Initialize(BranchesToKeep,"names");

        auto TwelMinimalFile=std::make_unique<TFile>("TwelMinimalFile.root","RECREATE");
        TTree* TwelMinimalTree=TwelReader->CopyTree("gamma_CL>0.1",-1,"DecayTree");
        TwelMinimalTree->Write();

        auto ElevMinimalFile=std::make_unique<TFile>("ElevMinimalFile.root","RECREATE");
        TTree* ElevMinimalTree=ElevReader->CopyTree("gamma_CL>0.1",-1,"DecayTree");
        ElevMinimalTree->Write();
    }
    if(recutmc) {
        DataFile MCTwel(std::getenv("BUKETAPMCROOT"),MC,Twel,MagAll,buketap,"TriggerCut");
        DataFile MCElev(std::getenv("BUKETAPMCROOT"),MC,Elev,MagAll,buketap,"TriggerCut");

        TreeReader* TwelReaderMC = new TreeReader("DecayTree");
        TwelReaderMC->AddFile(MCTwel);

        TreeReader* ElevReaderMC = new TreeReader("DecayTree");
        ElevReaderMC->AddFile(MCElev);


        TwelReaderMC->Initialize(BranchesToKeepMC,"names");
        ElevReaderMC->Initialize(BranchesToKeepMC,"names");

        auto TwelMinimalFileMC=std::make_unique<TFile>("TwelMinimalFileMC.root","RECREATE");
        TTree* TwelMinimalTreeMC=TwelReaderMC->CopyTree("gamma_CL>0.1",-1,"DecayTree");
        TwelMinimalTreeMC->Write();

        auto ElevMinimalFileMC=std::make_unique<TFile>("ElevMinimalFileMC.root","RECREATE");
        TTree* ElevMinimalTreeMC=ElevReaderMC->CopyTree("gamma_CL>0.1",-1,"DecayTree");
        ElevMinimalTreeMC->Write();
    }
    if(remakedatasets||recutmc||recutdata) {
        RooArgSet* MCVars= new RooArgSet("MCVars");
        RooArgSet* Vars= new RooArgSet("Vars");

        for(auto & Branch : BranchesToKeep) {
            Vars->add(*(HandyFunctions::CreateRealVar(Branch)));
        }

        for(auto & MCBranch:  BranchesToKeepMC) {
            MCVars->add(*(HandyFunctions::CreateRealVar(MCBranch)));
            std::cout<<MCBranch<<std::endl;
        }

        auto TwelMinimalFile = std::make_unique<TFile>("TwelMinimalFile.root");
        TTree* TwelMinimalTree=(TTree*)TwelMinimalFile->Get("DecayTree");
        std::cout<<"Tree Entreies = "<<TwelMinimalTree->GetEntries()<<std::endl;
        RooDataSet* TwelData= new RooDataSet("TwelData","TwelData",*Vars,Import(*TwelMinimalTree));
        std::cout<<"Events in Dataset= "<<TwelData->sumEntries()<<std::endl;

        auto ElevMinimalFile = std::make_unique<TFile>("ElevMinimalFile.root");
        TTree* ElevMinimalTree=(TTree*)ElevMinimalFile->Get("DecayTree");
        std::cout<<"Tree Entreies = "<<ElevMinimalTree->GetEntries()<<std::endl;
        RooDataSet* ElevData= new RooDataSet("ElevData","ElevData",*Vars,Import(*ElevMinimalTree));
        std::cout<<"Events in Dataset= "<<ElevData->sumEntries()<<std::endl;

        auto TwelMinimalFileMC = std::make_unique<TFile>("TwelMinimalFileMC.root");
        TTree* TwelMinimalTreeMC=(TTree*)TwelMinimalFileMC->Get("DecayTree");
        std::cout<<"Tree Entreies = "<<TwelMinimalTreeMC->GetEntries()<<std::endl;
        RooDataSet* TwelDataMC= new RooDataSet("TwelDataMC","TwelDataMC",*Vars,Import(*TwelMinimalTreeMC));
        std::cout<<"Events in Dataset= "<<TwelDataMC->sumEntries()<<std::endl;
        auto ElevMinimalFileMC = std::make_unique<TFile>("ElevMinimalFileMC.root");
        TTree* ElevMinimalTreeMC=(TTree*)ElevMinimalFileMC->Get("DecayTree");
        std::cout<<"Tree Entreies = "<<ElevMinimalTreeMC->GetEntries()<<std::endl;
        RooDataSet* ElevDataMC= new RooDataSet("ElevDataMC","ElevDataMC",*Vars,Import(*ElevMinimalTreeMC));
        std::cout<<"Events in Dataset= "<<ElevDataMC->sumEntries()<<std::endl;

        TwelMinimalFile->Close();
        ElevMinimalFile->Close();
        TwelMinimalFileMC->Close();
        ElevMinimalFileMC->Close();
        auto DataSetCache=std::make_unique<TFile>("DataSetCache.root","RECREATE");
        gDirectory->pwd();
        TwelData->Write();
        ElevData->Write();
        TwelDataMC->Write();
        ElevDataMC->Write();
    }

    TFile* DataSetCache= new TFile("DataSetCache.root");
    RooDataSet* Data12=SafeGetDataSet(DataSetCache,"TwelData");
    RooDataSet* Data11=SafeGetDataSet(DataSetCache,"ElevData");
    RooDataSet* MC12=SafeGetDataSet(DataSetCache,"TwelDataMC");
    RooDataSet* MC11=SafeGetDataSet(DataSetCache,"ElevDataMC");

    RooRealVar * BuMass= new RooRealVar("Bu_DTF_MF","Bu_DTF_MF",5000.0,5500.0);
    RooRealVar* BkgP1= new RooRealVar("BkgP1","BkgP1",-1.0,-10.0,10.0);
    RooRealVar* BkgP2= new RooRealVar("BkgP2","BkgP2",1.0,-10.0,10.0);
    RooChebychev* BkgPdf= new RooChebychev("BkgPdf","BkgPdf",*BuMass,RooArgList(*BkgP1,*BkgP2));

    BkgPdf->fitTo(*Data12,Range(5000.0,5200.));

    RooPlot* BFrame = BuMass->frame(Bins(50));
    Data12->plotOn(BFrame);
    BkgPdf->plotOn(BFrame);
    BkgPdf->paramOn(BFrame);
    TCanvas C;
    BFrame->Draw();

    C.SaveAs("BFrame.pdf");


}
int main(int argc, char** argv)
{
	string dataType = "12";
	//if(argc > 1) if((string)argv[1] == "11") dataType = "11";
	
	NeuroBayesTeacher* nb = NeuroBayesTeacher::Instance();
	
	nb->NB_DEF_TASK("CLASSIFICATION");
	
	//setup network topology
	int nvar = 20;  // Set this to number of inputs to your NN
	

	char ** varnames = new char*[nvar];
	varnames[0]  = "chi2_DTF";
	varnames[1]  = "Lb_TAU";
	varnames[2]  = "Lb_DIRA_OWNPV";
	varnames[3]  = "Lb_IPCHI2_OWNPV";
	varnames[4]  = "max_mu_IPCHI2_OWNPV";
	varnames[5]  = "min_mu_TRACKCHI2";
	varnames[6]  = "min_mu_PID";
	varnames[7]  = "min_mu_PID";
	varnames[8]  = "LL_Lambda0_IPCHI2_OWNPV";
	varnames[9] = "LL_Lambda0_FDCHI2_OWNPV";
	varnames[10] = "LL_Lambda0_PT";
	varnames[11] = "DD_Lambda0_IPCHI2_OWNPV";
	varnames[12] = "DD_Lambda0_FDCHI2_OWNPV";
	varnames[13] = "DD_Lambda0_PT";
	varnames[14]  = "DD_pplus_IPCHI2_OWNPV";
	varnames[15]  = "DD_piminus_IPCHI2_OWNPV";
	varnames[16]  = "DD_piminus_PT";
	varnames[17]  = "LL_pplus_IPCHI2_OWNPV";
	varnames[18]  = "LL_piminus_IPCHI2_OWNPV";
	varnames[19]  = "LL_piminus_PT";

	nb->NB_DEF_NODE1(nvar+1);
	nb->NB_DEF_NODE2(nvar);      // nodes in hidden layer 
	nb->NB_DEF_NODE3(1);       // nodes in output layer

	nb->NB_DEF_TASK("CLA");    // binominal classification

	nb->NB_DEF_PRE(822);
	//  nb->NB_DEF_PRE(812);
	nb->NB_DEF_REG("REG");           // 'OFF','REG' (def) ,'ARD','ASR','ALL'
	nb->NB_DEF_LOSS("ENTROPY");      // 'ENTROPY'(def),'QUADRATIC'
	nb->NB_DEF_METHOD("BFGS");
	nb->NB_DEF_SHAPE("DIAG");
	nb->NB_DEF_LEARNDIAG(1);

	nb->NB_DEF_RTRAIN(1.0);          // use 70% of events for training
	//  nb->NB_DEF_EPOCH(200);           // weight update after n events

	nb->NB_DEF_SPEED(2.0);           // multiplicative factor to enhance global learning speed
	nb->NB_DEF_MAXLEARN(1.0);        // multiplicative factor to limit the global learning speed in any direction, this number should be smaller than NB_DEF_SPEED

	nb->NB_DEF_ITER(100);             // number of training iteration
	//nb->NB_DEF_ITER(0);             // number of training iteration

    //int i = 4701;
	//int j = 29; 
	//nb->NB_RANVIN(i,j,2);            // random number seed initialisation, i has to be an odd number, the third argument is a debugging flag

	nb->SetOutputFile(("expert_"+dataType+".nb").c_str());  // expert file
	SetupNNPrepro(nb);
	
	// MC
	TreeReader* reader = new TreeReader("tree");
	reader->AddFile("/afs/cern.ch/work/p/pluca/Lmumu/weighted/Lb2Lmumu_MC_Pythia8_NBweighted_new.root");
	reader->Initialize();

	
	// We take all signal and 20% of background
	
	nb->SetTarget(1);
	int ntot = reader->GetEntries();
	int npassedMC = 0;
	
	cout << "Read in " << ntot << " events" << endl;
	
	int nstepMC = 5;
	//if(dataType=="11") nstepMC = 5;

	TFile ofile("/afs/cern.ch/work/p/pluca/Lmumu/weighted/samplesMVA_"+(TString)dataType+".root","recreate");
	TTree * sigTrainSample = new TTree("sigTrainSample","");
	reader->BranchNewTree(sigTrainSample);
	TTree * sigTestSample = new TTree("sigTestSample","");
	reader->BranchNewTree(sigTestSample);

	for(int event = 0; event < ntot; event++)
	{
		reader->GetEntry(event);
		
		if( TrueID(reader) && TriggerPassed(reader))
		{
			if( event%nstepMC==0 && npassedMC <= 4e4 )
			{
				npassedMC++;
				float InputArray[nvar+1];
				fillInputArray(reader,InputArray);
				if(isnan(InputArray[0])) continue;
				nb->SetWeight(reader->GetValue("Lb_weight"));
				nb->SetNextInput(nvar,InputArray);
				sigTrainSample->Fill();
			}
			else sigTestSample->Fill();
		}
	}


	// Data
	TreeReader* reader2 = new TreeReader("tree");
	reader2->AddFile("/afs/cern.ch/work/p/pluca/Lmumu/weighted/Lb2Lmumu_CL_NBweighted.root");
	reader2->Initialize();

	TTree * bkgTrainSample = new TTree("bkgTrainSample","");
	reader2->BranchNewTree(bkgTrainSample);
	TTree * bkgTestSample = new TTree("bkgTestSample","");
	reader2->BranchNewTree(bkgTestSample);

	nb->SetTarget(0);
	int ntot2 = reader2->GetEntries();
	int npassed = 0;
	
	cout << "Read in " << ntot2 << " events" << endl;
	int nstep = 2;
	//if(dataType=="11") nstep = 2;
	
	for(int event = 0; event < ntot2; event++)
	{
		reader2->GetEntry(event);
		
		double massLb = reader2->GetValue("Lb_MassConsLambda_M",0);
		double massJpsi = reader2->GetValue("J_psi_1S_MM");
		if(massLb > 6000 && TMath::Abs(massJpsi - 3096) > 100 && TMath::Abs(massJpsi - 3686) > 90 && TriggerPassed(reader2))
		{
			if(event%nstep==0 && npassed <=4e4)
			{
				float InputArray[100];
				npassed++;
				fillInputArray(reader2,InputArray);
				if(isnan(InputArray[0])) continue;
				nb->SetWeight(1.);
				nb->SetNextInput(nvar,InputArray);
				bkgTrainSample->Fill();
			}
			else bkgTestSample->Fill();
		}
	}
	
	bkgTrainSample->Write();
	bkgTestSample->Write();
	sigTestSample->Write();
	sigTrainSample->Write();
	ofile.Close();

	cout << "\nData used = " << npassed << ", MC used = " << npassedMC << endl;
	
	cout << "Train the Network\n" << endl;
	nb->TrainNet();
	nb->nb_correl_signi(varnames,"correl_signi.txt","correl_signi.html");

	cout << "\nData used = " << npassed << ", MC used = " << npassedMC << endl;
	
	return 0;
}