#include <TROOT.h>
#include <TSystem.h>
#include <TChain.h>
#include <TFile.h>
#include <TString.h>
#include <iostream>

//#define MONITORS

//Constants for analyses
//Event information
const int mPrimVertZbins = 6;                 //Number of z bins for analysis
const double mPrimVertZ[2] = {-30., 30.};     //Redefine values of the vertex Z for each run [cm]
const double mPrimVertR = 2.;                 //Distance in the XY plane [cm]
const double mPrimVertVpdVz[2] = {-5., 5.};   //VpdZ - TPCZ difference
const double mPrimVertXShift = 0.;
const double mPrimVertYShift = 0.;
const Bool_t mUseZdcCorrection = true;

//Track information
const double mChargedKaonMass = 0.493677;
const double mChargedPionMass = 0.13957018;
const int mPosCharge = +1;
const int mNegCharge = -1;
const int mTrackType = 1; 
const int mPythiaKaonCode = 321;              //Pythia particle code
//const int mPythiaPionCode = 211;              //Pythia particle code

const int mTrackNHits[2] = {15, 50};          //Number of track hits
const double mTrackNHitsFit[2] = {15, 50};     //Number of track hits used in fit
const double mTrackDCA[2] = {0., 2.};      //DCA of the track and PV [cm]
const double mTrackASplitVal = 0.52;
const double mTrackMom[2] = {0.15, 1.55};     //General momentum of the track [GeV/c]
const double mTrackTransvMom[2] = {0.15, 1.55};  //General transverse momentum of the track [GeV/c]
const double mTrackEta[2] = { -1., 1.};

const short mDetectorSelection = 2;   //TPC+TOF

const double mTrackTpcMom[2] = {0.15, 0.55};  //Track momentum for TPC idnetification [GeV/c]
const double mnSigmaElectron[2] = {-1e9, 1e9};
const double mnSigmaPion[2] = {-1e9., 1e9};
const double mnSigmaKaon[2] = {-2., 2.};
const double mnSigmaProton[2] = {-1e9, 1e9};

const double mTrackTofMom[2] = {0.15, 1.55};   //Track momentum for ToF identification [GeV/c]
const double mPionTofMsqr[2] = {-0.02, 0.062}; //Based on p+p data
const double mKaonTofMsqr[2] = {0.20, 0.32};    //Based on p+p data

const double mTrackTnTMom[2] = {0.15, 1.55};
const double mTnTNSigmaElectron[2] = {-1e9, 1e9};
const double mTnTNSigmaPion[2] = {-1e9., 1e9};
const double mTnTNSigmaKaon[2] = {-3., 3.};
const double mTnTNSigmaProton[2] = {-1e9, 1e9};

const double mTTTMomThresh = 0.45; // 0-TPC, 1-ToF, 2-TPC+ToF, 3-ToF||TPC, 4-TPC&&TOF(P>Pthr)||TPC(P<Pthr)

//Pair information
const double mFmrCut[2] = {-1.1, 0.1};        //Not more than 10% of merged rows
const double mSplitLevelCut[2] = {-0.5, 0.6}; //Splitting level from paper. StHbtPair::quality()
const double mPairKt[2] = {0.,1.5};           //Pair transverse momentum cut
const double mPairQinv[2] = {0., 1.5};        //Pair relative momentum
const double mAveSep[2] = {5., 5000.};         //Average separation of tracks within TPC

//Histograms values
const int mPairKtBins = 20;
const double mPairKtVal[2] = {0., 1.};
const int mQinvBins = 40;                       //10 MeV/c^2 bin width
const double mQinvVal[2] = {0., 0.4};          //Redefine for each analysis

const Char_t *defaultInFile = "/star/data01/pwg/pusheax/devel/dataset/st_physics_12153012_raw_1030005.MuDst.root";
const Char_t *defaultOutFile = "oExpKaon_auau200_3D.root";

//_________________
void expKaonHBT_auau200_3D(const Char_t *inFileList = defaultInFile,
			    const Char_t *oFileName = defaultOutFile) {

  std::cout << "*********************************" << std::endl
	    << "*     expKaonHBT_auau200_3D     *" << std::endl
	    << "*              Start            *" << std::endl
	    << "*********************************" << std::endl << endl;

  //Load libraries
  std::cout << "Loading libraries..." << std::endl;
  gROOT->LoadMacro("$STAR/StRoot/StMuDSTMaker/COMMON/macros/loadSharedLibraries.C");
  loadSharedLibraries();
  gSystem->Load("libMinuit");
  gSystem->Load("StRefMultCorr");
  gSystem->Load("StFlowMaker");   //Should be placed before HBT
  gSystem->Load("StHbtMaker");
  gSystem->Load("StarClassLibrary");
  gSystem->Load("libgsl");
  gSystem->Load("libgslcblas");

  std::cout << "Libraries have been successfully loaded" << std::endl;

  //Create chain
  StChain* mChain = new StChain("StChain");
  mChain->SetDebug(0);
  StMuDebug::setLevel(0);

  //Set muDstMaker
  Int_t nMaxFileToRead = 1e9;
  std::cout << Form("Try to read file: %s", inFileList) << std::endl;
  StMuDstMaker *mMuDstMaker = 
    new StMuDstMaker(0, 0, "", inFileList, "MuDst", nMaxFileToRead);

  mMuDstMaker->SetStatus("*",0);
  mMuDstMaker->SetStatus("Event*",1);
  mMuDstMaker->SetStatus("MuEvent*",1);
  mMuDstMaker->SetStatus("PrimaryVertices*",1);
  mMuDstMaker->SetStatus("PrimaryTracks*",1);
  mMuDstMaker->SetStatus("GlobalTracks*",1);
  mMuDstMaker->SetStatus("BTofHeader*",1);

  TChain *mCurrentTree = mMuDstMaker->chain();
  Long64_t mNEvents = mCurrentTree->GetEntries();
  std::cout << Form("Number of events in TTree: %d", mNEvents) << std::endl;

  //Set StHbtMaker and StHbtManager
  StHbtMaker *mHbtMaker = new StHbtMaker();
  mHbtMaker->SetDebug(0);
  StHbtManager *mHbtManager = mHbtMaker->HbtManager();

  //Set StHbtReader
  gregsStHbtMuDstReader* mHbtMuDstMakerReader = new gregsStHbtMuDstReader(mMuDstMaker);
  mHbtMuDstMakerReader->setTrackType(1);
  mHbtMuDstMakerReader->setReadTracks(true);
  mHbtMuDstMakerReader->setReadV0s(false);
  mHbtMuDstMakerReader->AddTriggerId(350003);          //mb-protected
  mHbtMuDstMakerReader->AddTriggerId(350013);          //mb-protected
  mHbtMuDstMakerReader->AddTriggerId(350023);          //mb-protected
  mHbtMuDstMakerReader->AddTriggerId(350033);          //mb-protected
  mHbtMuDstMakerReader->AddTriggerId(350043);          //mb-protected
  mHbtMuDstMakerReader->SetProcessAllVertices(false);
  mHbtManager->SetEventReader(mHbtMuDstMakerReader);

  //Set basic event cut
  gregsEventCut *mBasicEventCut = new gregsEventCut();
  mBasicEventCut->SetCollisionType(1);     //0-pp, 1-AuAu
  mBasicEventCut->SetEventMult(0, 1000);
  mBasicEventCut->SetVertZPos(mPrimVertZ[0], mPrimVertZ[1]);
  mBasicEventCut->SetVzVpdVzDiff(mPrimVertVpdVz[0],mPrimVertVpdVz[1]);
  mBasicEventCut->SetVertRPos(mPrimVertR);
  mBasicEventCut->SetCentralityDefinition(mCentBins);
  mBasicEventCut->SetEventCentralityBins(0, 8);  //For 9 centrality bins
  mBasicEventCut->SetZdcRefMultCorrection(mUseZdcCorrection);

  //Set basic kaon single-particle cut
  gregsSimpleTrackCut *mBasicTrackCut = new gregsSimpleTrackCut();
  mBasicTrackCut->SetCharge(mPosCharge);
  mBasicTrackCut->SetMass(mChargedKaonMass);
  mBasicTrackCut->SetType(mTrackType);
  mBasicTrackCut->SetNHits(mTrackNHits[0], mTrackNHits[1]);
  mBasicTrackCut->SetNHitsFit(mTrackNHitsFit[0], mTrackNHitsFit[1]);
  mBasicTrackCut->SetAntiSplit(mTrackASplitVal);
  mBasicTrackCut->SetEta(mTrackEta[0], mTrackEta[1]);
  mBasicTrackCut->SetDCA(mTrackDCA[0], mTrackDCA[1]);
  mBasicTrackCut->SetDCAGlobal(mTrackDCA[0], mTrackDCA[1]);
  mBasicTrackCut->SetP(mTrackMom[0], mTrackMom[1]);

  mBasicTrackCut->SetDetectorSelection(mDetectorSelection);

  mBasicTrackCut->SetTpcMomentum(mTrackTpcMom[0], mTrackTpcMom[1]);
  mBasicTrackCut->SetNSigmaElectron(mnSigmaElectron[0],mnSigmaElectron[1]);
  mBasicTrackCut->SetNSigmaPion(mnSigmaPion[0], mnSigmaPion[1]);
  mBasicTrackCut->SetNSigmaKaon(mnSigmaKaon[0], mnSigmaKaon[1]);
  mBasicTrackCut->SetNSigmaProton(mnSigmaProton[0], mnSigmaProton[1]);

  mBasicTrackCut->SetTofMassSqr(mKaonTofMsqr[0],mKaonTofMsqr[1]);
  mBasicTrackCut->SetTofMomentum(mTrackTofMom[0], mTrackTofMom[1]);

  mBasicTrackCut->SetTnTMomentum(mTrackTnTMom[0], mTrackTnTMom[1]);
  mBasicTrackCut->SetTnTNSigmaElectron(mTnTNSigmaElectron[0], mTnTNSigmaElectron[1]);
  mBasicTrackCut->SetTnTNSigmaPion(mTnTNSigmaPion[0], mTnTNSigmaPion[1]);
  mBasicTrackCut->SetTnTNSigmaKaon(mTnTNSigmaKaon[0], mTnTNSigmaKaon[1]);
  mBasicTrackCut->SetTnTNSigmaProton(mTnTNSigmaProton[0], mTnTNSigmaProton[1]);

  mBasicTrackCut->SetTTTMomentumThresh(mTTTMomThresh);

  //Set basic kaon pair cut
  gregsTrackPairCut *mBasicPairCut = new gregsTrackPairCut();
  mBasicPairCut->SetFracOfMergedRow(mFmrCut[0],mFmrCut[1]);
  mBasicPairCut->SetQuality(mSplitLevelCut[0],mSplitLevelCut[1]);
  mBasicPairCut->SetKt(mPairKt[0],mPairKt[1]);
  mBasicPairCut->SetQinv(mPairQinv[0],mPairQinv[1]);
  mBasicPairCut->SetAverageSeparation(mAveSep[0],mAveSep[1]);

  Int_t mLocalCharge, mMultBins, mMultLow, mMultHi, mEvents2Mix;
  Int_t mCentLo, mCentHi;
  Float_t mKtLo, mKtHi;

  ////////////////////////////////////////////
  //                                        //
  //       Like-sign meson analysis         //
  //                                        //
  ////////////////////////////////////////////

  //The multiplicity analysis matrix is 2x5x5, where
  //the first element corresponds to the particle charge: (pos, neg),
  //and 5 centralitiy bins: (0-5),(5-10),(10-20),(20-30),(30-80)
  //kT bins will be: (0.1-0.35),(0.35-0.5),(0.5-0.65),(0.65-0.8),(0.8-1.1)

  //StHbtAnalysis, cut, CF and monitor declarations
  StHbtVertexMultAnalysis *mKaonMultAnalysis[2][5][5];

  //Cuts
  gregsEventCut *mKaonEventCut[2][5][5];
  gregsSimpleTrackCut *mKaonTrackCut[2][5][5];
  gregsTrackPairCut *mKaonPairCut[2][5][5];

  //CorrFctns
  BPLCMSFrame3DCorrFctn *mKaonBPlcmsCorrFctn[2][5][5];

#ifdef MONITORS
  //Cut monitors
  fxtEventCutMonitor* mFxtKaonEventCutMonitorPass[2][5][5];
  fxtTrackCutMonitor* mFxtKaonTrackCutMonitorPass[2][5][5];
  fxtPairCutMonitor* mFxtKaonPairCutMonitorPass[2][5][5];
  fxtEventCutMonitor* mFxtKaonEventCutMonitorFail[2][5][5];
  fxtTrackCutMonitor* mFxtKaonTrackCutMonitorFail[2][5][5];
  fxtPairCutMonitor* mFxtKaonPairCutMonitorFail[2][5][5];

#endif

  for(Int_t iCharge=0; iCharge<2; iCharge++) {
    for(Int_t iMult=0; iMult<5; iMult++) {
      for(Int_t iKt=0; iKt<5; iKt++) {

	switch(iCharge) {
	case 0:  mLocalCharge = mPosCharge;    break;
	case 1:  mLocalCharge = mNegCharge;    break;
	default: mLocalCharge = mPosCharge;    break;
	};

        switch(iMult) {
        case 0: mCentLo=8; mCentHi=8; mMultLow=466; mMultHi=800;  mMultBins=2; mEvents2Mix=3; break;
        case 1: mCentLo=7; mCentHi=7; mMultLow=396; mMultHi=465;  mMultBins=2; mEvents2Mix=3; break;
	case 2: mCentLo=6; mCentHi=6; mMultLow=281; mMultHi=395;  mMultBins=2; mEvents2Mix=3; break;
        case 3: mCentLo=5; mCentHi=5; mMultLow=193; mMultHi=280;  mMultBins=2; mEvents2Mix=3; break;
        case 4: mCentLo=0; mCentHi=4; mMultLow=10;  mMultHi=192;  mMultBins=5; mEvents2Mix=5; break;
	default: mCentLo=0; mCentHi=8; mMultLow=10;  mMultHi=800;  mMultBins=10; mEvents2Mix=5; break;
        };

	switch(iKt) {
	case 0:  mKtLo=0.10; mKtHi=0.35; break;
	case 1:  mKtLo=0.35; mKtHi=0.50; break;
	case 2:  mKtLo=0.50; mKtHi=0.65; break;
	case 3:  mKtLo=0.65; mKtHi=0.80; break;
	case 4:  mKtLo=0.80; mKtHi=1.10; break;
	default: mKtLo=0.10; mKtHi=0.35; break;
	};

	/////////////////////////////////////
	//                                 //
	//      Like-sign kaon analysis    //
	//                                 //
	/////////////////////////////////////

	//Create analysis
	mKaonMultAnalysis[iCharge][iMult][iKt] = new StHbtVertexMultAnalysis(mPrimVertZbins,
									      mPrimVertZ[0],
									      mPrimVertZ[1],
									      mMultBins,
									      mMultLow,
									      mMultHi);

	//Create event cut
	mKaonEventCut[iCharge][iMult][iKt] = new gregsEventCut(*mBasicEventCut);
	mKaonEventCut[iCharge][iMult][iKt]->SetCentralityDefinition(mCentBins);
	mKaonEventCut[iCharge][iMult][iKt]->SetEventCentralityBins(mCentLo, mCentHi);
	mKaonEventCut[iCharge][iMult][iKt]->SetZdcRefMultCorrection(mUseZdcCorrection);

	mKaonTrackCut[iCharge][iPid][iKt]->SetTpcMomentum(0.15, 0.55);
	mKaonTrackCut[iCharge][iPid][iKt]->SetNSigmaElectron(-1e9,1e9);
	mKaonTrackCut[iCharge][iPid][iKt]->SetNSigmaPion(-1e9, 1e9);
	mKaonTrackCut[iCharge][iPid][iKt]->SetNSigmaKaon(-2., 2.);
	mKaonTrackCut[iCharge][iPid][iKt]->SetNSigmaProton(-1e9, 1e9);

	mKaonTrackCut[iCharge][iPid][iKt]->SetTofMassSqr(0.20, 0.32);
	mKaonTrackCut[iCharge][iPid][iKt]->SetTofMomentum(0.15, 1.55);

	mKaonTrackCut[iCharge][iPid][iKt]->SetTnTMomentum(0.15, 1.55);
	mKaonTrackCut[iCharge][iPid][iKt]->SetTnTNSigmaElectron(-1e9, 1e9);
	mKaonTrackCut[iCharge][iPid][iKt]->SetTnTNSigmaPion(-1e9, 1e9);
	mKaonTrackCut[iCharge][iPid][iKt]->SetTnTNSigmaKaon(-3., 3.);
	mKaonTrackCut[iCharge][iPid][iKt]->SetTnTNSigmaProton(-1e9, 1e9);

	mKaonTrackCut[iCharge][iPid][iMult]->SetTTTMomentumThresh(0.45);
	
#ifdef MONITORS
	mFxtKaonEventCutMonitorPass[iCharge][iMult][iKt] = 
	  new fxtEventCutMonitor("eventKaonPass", Form("_%d_%d_%d",iCharge,iMult,iKt));
	mFxtKaonEventCutMonitorFail[iCharge][iMult][iKt] = 
	  new fxtEventCutMonitor("eventKaonFail", Form("_%d_%d_%d",iCharge,iMult,iKt));
	mKaonEventCut[iCharge][iMult][iKt]->AddCutMonitor(mFxtKaonEventCutMonitorPass[iCharge][iMult][iKt],
							   mFxtKaonEventCutMonitorFail[iCharge][iMult][iKt]);
#endif
	mKaonMultAnalysis[iCharge][iMult][iKt]->SetEventCut(mKaonEventCut[iCharge][iMult][iKt]);


	//Create single-track cuts and add them to the analysis
	mKaonTrackCut[iCharge][iMult][iKt] = new gregsSimpleTrackCut(*mBasicTrackCut);
	mKaonTrackCut[iCharge][iMult][iKt]->SetMass(mChargedKaonMass);
	//mKaonTrackCut[iCharge][iMult][iKt]->SetDetectorSelection(mCurrentPid);
	mKaonTrackCut[iCharge][iMult][iKt]->SetCharge(mLocalCharge);
#ifdef MONITORS
	mFxtKaonTrackCutMonitorPass[iCharge][iMult][iKt] = 
	  new fxtTrackCutMonitor(Form("_trackKaonPass_%d_%d_%d_",iCharge,iMult,iKt), mChargedKaonMass);
	mFxtKaonTrackCutMonitorFail[iCharge][iMult][iKt] = 
	  new fxtTrackCutMonitor(Form("_trackKaonFail_%d_%d_%d_",iCharge,iMult,iKt), mChargedKaonMass);
	mKaonTrackCut[iCharge][iMult][iKt]->AddCutMonitor(mFxtKaonTrackCutMonitorPass[iCharge][iMult][iKt],
							   mFxtKaonTrackCutMonitorFail[iCharge][iMult][iKt]);
#endif
	mKaonMultAnalysis[iCharge][iMult][iKt]->SetFirstParticleCut(mKaonTrackCut[iCharge][iMult][iKt]);
	mKaonMultAnalysis[iCharge][iMult][iKt]->SetSecondParticleCut(mKaonTrackCut[iCharge][iMult][iKt]);

	//Create pair cut
	mKaonPairCut[iCharge][iMult][iKt] = new gregsTrackPairCut(*mBasicPairCut);
	mKaonPairCut[iCharge][iMult][iKt]->SetKt(mKtLo, mKtHi);

#ifdef MONITORS
	mFxtKaonPairCutMonitorPass[iCharge][iMult][iKt] = 
	  new fxtPairCutMonitor(Form("_pairKaonPass_%d_%d_%d_",iCharge,iMult,iKt));
	mFxtKaonPairCutMonitorPass[iCharge][iMult][iKt]->SetParticleMass(mChargedKaonMass);
	mFxtKaonPairCutMonitorFail[iCharge][iMult][iKt] = 
	  new fxtPairCutMonitor(Form("_pairKaonFail_%d_%d_%d_",iCharge,iMult,iKt));
	mFxtKaonPairCutMonitorFail[iCharge][iMult][iKt]->SetParticleMass(mChargedKaonMass);
	mKaonPairCut[iCharge][iMult][iKt]->AddCutMonitor(mFxtKaonPairCutMonitorPass[iCharge][iMult][iKt],
							  mFxtKaonPairCutMonitorFail[iCharge][iMult][iKt]);
#endif
	mKaonMultAnalysis[iCharge][iMult][iKt]->SetPairCut(mKaonPairCut[iCharge][iMult][iKt]);

	//Correlation function initialization
	mKaonBPlcmsCorrFctn[iCharge][iMult][iKt] = 
	  new BPLCMSFrame3DCorrFctn(Form("mKaonBPlcmsCorrFctn_%d_%d_%d",iCharge,iMult,iKt),
				    mQinvBins, -mQinvVal[1], mQinvVal[1]);
	mKaonBPlcmsCorrFctn[iCharge][iMult][iKt]->SetNormRangeLo(0.20);
	mKaonBPlcmsCorrFctn[iCharge][iMult][iKt]->SetNormRangeHi(0.35);

	mKaonMultAnalysis[iCharge][iMult][iKt]->AddCorrFctn(mKaonBPlcmsCorrFctn[iCharge][iMult][iKt]);
	//Set number of events to mix
	mKaonMultAnalysis[iCharge][iMult][iKt]->SetNumEventsToMix(mEvents2Mix);

	//Add analysis to the manager
	mHbtManager->AddAnalysis(mKaonMultAnalysis[iCharge][iMult][iKt]);

      } //for(Int_t iKt=0; iKt<5; iKt++)
    } //for(Int_t iMult=0; iMult<5; iMult++)
  } //for(Int_t iCharge=0; iCharge<2; iCharge++)

  //StChain initialization
  mChain->Init();

  //Start processing
  Int_t iRet = 0;
  Int_t mNEventsProcessed = 0;
  Float_t mPercentCounter = 0.05;
  Float_t mProgress = 0.;

  unsigned int mSubCounter = 1;              // time
  time_t mStartTime, mStopTime, mDiffTime;   // time
  float mFrac;                               // time
  mStartTime = time(0);                      // time

  //mNEvents = 15;
  for(Int_t iEvent=0; iEvent<mNEvents; iEvent++) {

    mProgress = (Float_t)iEvent / (Float_t)mNEvents;
    mNEventsProcessed++;
    
    if(mProgress >= mPercentCounter) {
      mPercentCounter += 0.05;
      mStopTime = time(0);
      mDiffTime = difftime(mStopTime, mStartTime);
      mFrac = (float)mDiffTime*(float)(mNEvents - iEvent)/(float)iEvent;
      mSubCounter++;
      std::cout << Form("Processing progress: %4.2f%%. Time left: %.1f sec", mProgress*100., mFrac)
		<< std::endl;
    }

    mChain->Clear();
    iRet = mChain->Make(iEvent);
    if(iRet!=0) {
      std::cout << "expKaonHBT_auau200_3D[ERROR] - iRet: " << iRet << std::endl;
      break;
    }
  }

  mChain->Finish();

  //Create output file
  TFile *oFile = new TFile(oFileName, "RECREATE");

  //Write hbt histograms to the file
  std::cout << "Writing histograms to the output file...";

#ifdef MONITORS
  for(Int_t iCharge=0; iCharge<2; iCharge++) {
      for(Int_t iMult=0; iMult<5; iMult++) {
	for(Int_t iKt=0; iKt<5; iKt++) {

        //Kaons
        mFxtKaonEventCutMonitorPass[iCharge][iPid][iMult]->VertexZ()->Write();
	mFxtKaonEventCutMonitorPass[iCharge][iPid][iMult]->VertexYvsVertexX()->Write();
	mFxtKaonEventCutMonitorPass[iCharge][iPid][iMult]->RefMult()->Write();
	mFxtKaonEventCutMonitorPass[iCharge][iPid][iMult]->VpdVzDiff()->Write();
	mFxtKaonEventCutMonitorFail[iCharge][iPid][iMult]->VertexZ()->Write();
	mFxtKaonEventCutMonitorFail[iCharge][iPid][iMult]->VertexYvsVertexX()->Write();
	mFxtKaonEventCutMonitorFail[iCharge][iPid][iMult]->RefMult()->Write();
	mFxtKaonEventCutMonitorFail[iCharge][iPid][iMult]->VpdVzDiff()->Write();

	mFxtKaonTrackCutMonitorPass[iCharge][iPid][iMult]->DCAGlobal()->Write();
	mFxtKaonTrackCutMonitorPass[iCharge][iPid][iMult]->Nhits()->Write();
	mFxtKaonTrackCutMonitorPass[iCharge][iPid][iMult]->P()->Write();
	mFxtKaonTrackCutMonitorPass[iCharge][iPid][iMult]->Pt()->Write();
	mFxtKaonTrackCutMonitorPass[iCharge][iPid][iMult]->PtVsNsigmaPion()->Write();
	mFxtKaonTrackCutMonitorPass[iCharge][iPid][iMult]->PtVsNsigmaKaon()->Write();
	mFxtKaonTrackCutMonitorPass[iCharge][iPid][iMult]->PtVsNsigmaProton()->Write();
	mFxtKaonTrackCutMonitorPass[iCharge][iPid][iMult]->PvsDedx()->Write();
	mFxtKaonTrackCutMonitorPass[iCharge][iPid][iMult]->Rapidity()->Write();
	mFxtKaonTrackCutMonitorPass[iCharge][iPid][iMult]->PseudoRapidity()->Write();
	mFxtKaonTrackCutMonitorPass[iCharge][iPid][iMult]->PtVsMassSqr()->Write();
	mFxtKaonTrackCutMonitorFail[iCharge][iPid][iMult]->DCAGlobal()->Write();
	mFxtKaonTrackCutMonitorFail[iCharge][iPid][iMult]->Nhits()->Write();
	mFxtKaonTrackCutMonitorFail[iCharge][iPid][iMult]->P()->Write();
	mFxtKaonTrackCutMonitorFail[iCharge][iPid][iMult]->Pt()->Write();
	mFxtKaonTrackCutMonitorFail[iCharge][iPid][iMult]->PtVsNsigmaPion()->Write();
	mFxtKaonTrackCutMonitorFail[iCharge][iPid][iMult]->PtVsNsigmaKaon()->Write();
	mFxtKaonTrackCutMonitorFail[iCharge][iPid][iMult]->PtVsNsigmaProton()->Write();
	mFxtKaonTrackCutMonitorFail[iCharge][iPid][iMult]->PvsDedx()->Write();
	mFxtKaonTrackCutMonitorFail[iCharge][iPid][iMult]->Rapidity()->Write();
	mFxtKaonTrackCutMonitorFail[iCharge][iPid][iMult]->PseudoRapidity()->Write();
	mFxtKaonTrackCutMonitorFail[iCharge][iPid][iMult]->PtVsMassSqr()->Write();

	mFxtKaonPairCutMonitorPass[iCharge][iPid][iMult]->Kt()->Write();
	mFxtKaonPairCutMonitorPass[iCharge][iPid][iMult]->Pt1Pt2Qinv()->Write();
	mFxtKaonPairCutMonitorPass[iCharge][iPid][iMult]->FMRvsQinv()->Write();
	mFxtKaonPairCutMonitorPass[iCharge][iPid][iMult]->SLvsQinv()->Write();
	mFxtKaonPairCutMonitorPass[iCharge][iPid][iMult]->AveSepVsQinv()->Write();
	mFxtKaonPairCutMonitorFail[iCharge][iPid][iMult]->Kt()->Write();
	mFxtKaonPairCutMonitorFail[iCharge][iPid][iMult]->Pt1Pt2Qinv()->Write();
	mFxtKaonPairCutMonitorFail[iCharge][iPid][iMult]->FMRvsQinv()->Write();
	mFxtKaonPairCutMonitorFail[iCharge][iPid][iMult]->SLvsQinv()->Write();
	mFxtKaonPairCutMonitorFail[iCharge][iPid][iMult]->AveSepVsQinv()->Write();

      } //for(Int_t iKt=0; iKt<5; iKt++) {
    } //for(Int_t iMult=0; iMult<10; iMult++)
  } //for(Int_t iCharge=0; iCharge<2; iCharge++)
#endif

  for(Int_t iCharge=0; iCharge<2; iCharge++) {
    for(Int_t iMult=0; iMult<5; iMult++) {
      for(Int_t iKt=0; iKt<5; iKt++) {
	
	//Kaon analysis
	mKaonBPlcmsCorrFctn[iCharge][iMult][iKt]->Numerator()->Write();
	mKaonBPlcmsCorrFctn[iCharge][iMult][iKt]->UncorrectedDenominator()->Write();
	mKaonBPlcmsCorrFctn[iCharge][iMult][iKt]->QinvHisto()->Write();

      } //for(Int_t iKt=0; iKt<mPairKtBins; iKt++)
    } //for(Int_t iMult=0; iMult<10; iMult++)
  } //for(Int_t iCharge=0; iCharge<2; iCharge++

  std::cout << "\t[DONE]" << std::endl;

  //Write the output file and close it
  std::cout << "Saving the output file...";
  oFile->Write();
  oFile->Close();
  std::cout << "\t[DONE]" << std::endl;

  delete mChain;

  std::cout << "*********************************" << std::endl
	    << "*      expKaonHBT_auau200_3D    *" << std::endl
	    << "*              Finish           *" << std::endl
	    << "*********************************" << std::endl << std::endl;
}
