Example #1
0
void exampleStMuIOMaker(const char* file="/star/data14/reco/productionCentral/ReversedFullField/P02ge/2001/324/st_physics_2324001_raw_0006.MuDst.root") {
  gROOT->LoadMacro("$STAR/StRoot/StMuDSTMaker/COMMON/macros/loadSharedLibraries.C");
  loadSharedLibraries();

  StMuDebug::setLevel(0);  

  int counter=0;
  int iret=0;

  StMuIOMaker* maker = new StMuIOMaker("MuDst");  
  maker->SetFileAndOpen(file);
//  maker->SetFileName("st_physics_2313018_raw_0029.MuDst.root");
  TMemStat memStat("exampleMuIO");

  StMuDst* mu;
// evtid is an unique id of an event in a run which may involve several files!
// it is different from sequential index in a run which starts from "0"!
//  for ( int evtid=80673; evtid<80694; evtid++) {
//  for ( int evtid=6300; evtid<6321; evtid++) {
//	iret = maker->Make( StUKey(2271008,evtid) );  
//	iret = maker->Make( StUKey(2313018,evtid) );  
// alterative
for ( int i=0; i<20; i++) {
//	iret = maker->Make();  // read an event in natural sequential 
	iret = maker->Make(i);  // read an event with seqential index 
	if ( iret == kStOK) {
	   StMuDst* mu = maker->muDst();
	   if ( !mu ) continue;
//           if(i%10 != 0) continue;

// take a look at branches of tracks
	   int n;
	   n= mu->globalTracks()->GetEntries();
	   for (int l=0; l<n; l++) globalPt.Fill(mu->globalTracks(l)->pt());   
	   n= mu->primaryTracks()->GetEntries();
	   for (int l=0; l<n; l++) primaryPt.Fill(mu->primaryTracks(l)->pt()); 
	   n= mu->l3Tracks()->GetEntries();
	   for (int l=0; l<n; l++) {l3Pt.Fill( mu->l3Tracks(l)->pt() );}   

// take a look at event branch 
	   StMuEvent* muEvent = mu->event();
	   int referenceMultiplicity = muEvent->refMult();
	   refMult.Fill(referenceMultiplicity);

	   cout << "#" << i << " index=" << maker->currentIndex()
//	   cout << "eventId =" << evtid << " index=" << maker->currentIndex() 
                << " refmult= "<< referenceMultiplicity
	        << " used= "<< memStat.Used()
	        << " size= "<< memStat.ProgSize() << endl;
	   counter++;
	}
  }
  cout << " # of events:" << counter << endl;

  globalPt.Draw();
  primaryPt.Draw("same");
  l3Pt.Draw("same");
 
  TFile f("testMuIO.root","RECREATE");
  globalPt.Write();
  primaryPt.Write();
  l3Pt.Write();
  refMult.Write();
  f.Close();
}
Example #2
0
/**
 * 1. Data sample : pp200 W->e nu with  pile-up corresponding to 1 MHz min. bias
 * events, 50 K event y2011, 10 K event y2012.
 *
 * 2. Proof of principal: no pile-up for both PPV and KFV
 *
 *   a.  Reconstructed primary track multiplicity versus corresponding MC
 *   "reconstructable" (i.e. in n STAR acceptance,no. TPC MC hits >= 15)  tracks
 *   multiplicity.
 *
 *   b.  Corrected reconstructed primary track multiplicity (i.e. multiplied by
 *   QA/100.) versus corresponding MC "reconstructable"  (i.e. in n STAR
 *   acceptance,no. TPC MC hits >= 15)  tracks multiplicity.
 *
 *   c.  Efficiency primary vertex reconstruction versus  MC "reconstructable"
 *   tracks multiplicity.
 *
 * 3. With pileup. repeat above (a-c) with old ranking scheme for
 *
 *     I. Any reconstructed primary vertex which is matched with MC trigger
 *     vertex (MC = 1)
 *
 *    II. The best (in sense of ranking) reconstructed primary vertex which is
 *    matched with MC trigger vertex (MC = 1)
 *
 *   III. The best (in sense of ranking) reconstructed primary vertex which is
 *   not matched with MC trigger vertex (MC != 1)
 *
 * 4. With pileup. repeat above (a-c) with new ranking scheme for cases I-III
 */
void MuMcPrVKFV2012(Long64_t nevent, const char *file, const std::string& outFile, bool fillNtuple)
{
#ifdef __TMVA__
   boost::replace_last(outFile, ".root", "");
   outFile += ".TMVArank.root";

   // create a set of variables and declare them to the reader
   // - the variable names must corresponds in name and type to
   // those given in the weight file(s) that you use
   TString separator(":");
   TString Vnames(vnames);
   TObjArray *array = Vnames.Tokenize(separator);

   std::vector<std::string> inputVars;
   TIter next(array);
   TObjString *objs;

   while ((objs = (TObjString *) next())) {
      std::cout << objs->GetString() << std::endl;
   }

   inputVars.push_back("beam");
   inputVars.push_back("postx");
   inputVars.push_back("prompt");
   inputVars.push_back("cross");
   inputVars.push_back("tof");
   inputVars.push_back("notof");
   inputVars.push_back("EEMC");
   inputVars.push_back("noEEMC");
   inputVars.push_back("chi2");

   std::vector<double> *inputVec = new std::vector<double>( inputVars.size() );
   IClassifierReader *classReader = new ReadBDT( inputVars );

#endif /* __TMVA__ */

   TFile *fOut = TFile::Open(outFile.c_str(), "recreate");
   data_t data;

   // Book histograms
   const int nMcRecMult = 75;
   TArrayD xMult(nMcRecMult + 1);
   xMult[0] = -0.5;

   for (int i = 1; i <= nMcRecMult; i++) {
      if      (xMult[i - 1] <  50) xMult[i] = xMult[i - 1] +   1; //  1 - 50
      else if (xMult[i - 1] < 100) xMult[i] = xMult[i - 1] +   2; // 51 - 75
      else if (xMult[i - 1] < 200) xMult[i] = xMult[i - 1] +  10; // 76 - 85
      else                         xMult[i] = xMult[i - 1] + 100; // 86 -100
   }

   TH1D *McRecMulT = new TH1D("McRecMulT", "Reconstructable multiplicity for trigger Mc Vertex", nMcRecMult, xMult.GetArray());
   struct Name_t {
      const Char_t *Name;
      const Char_t *Title;
   };
   const Name_t HCases[3] = {
      {"Any", "Any vertex matched with MC == 1"},
      {"Good", "The best rank vertex with MC == 1"},
      {"Bad", "The best rank vertex with MC != 1"}
   };
   const Name_t Plots[4] = {
      {"Mult"    , "the reconstructed (uncorrected) track multiplicity versus Reconstructable multiplicity"},
      {"MultQA"  , "the reconstructed (corrected for QA) track multiplicity versus Reconstructable multiplicity"},
      {"McRecMul", "Reconstructable multiplicity"},
      {"YvsX"    , "Bad versus Good value"}
   };
   /*         h  p  */
   TH1 *hists[3][4];

   for (int h = 0; h < 3; h++) {
      for (int p = 0; p < 4; p++) {
         TString Name(Plots[p].Name); Name += HCases[h].Name;
         TString Title(Plots[p].Title); Title += " for "; Title += HCases[h].Title; Title += " vertex";

         if      (p <  2)  hists[h][p] = new TH2D(Name, Title, nMcRecMult, xMult.GetArray(), nMcRecMult, xMult.GetArray());
         else if (p == 2)  hists[h][p] = new TH1D(Name, Title, nMcRecMult, xMult.GetArray());
      }
   }

   TNtuple *VertexG = new TNtuple("VertexG", "good vertex & global params info", vnames);
   TNtuple *VertexB = new TNtuple("VertexB", "bad  vertex & global params info", vnames);
   // ----------------------------------------------
   StMuDstMaker *maker = new StMuDstMaker(0, 0, "", file, "st:MuDst.root", 1e9); // set up maker in read mode
   //                       0,0                        this mean read mode
   //                           dir                    read all files in this directory
   //                               file               bla.lis real all file in this list, if (file!="") dir is ignored
   //                                    filter        apply filter to filenames, multiple filters are separated by ':'
   //                                          10      maximum number of file to read
   maker->SetStatus("*", 0);

   std::vector<std::string> activeBranchNames = {
      "MuEvent",
      "PrimaryVertices",
      "StStMuMcVertex",
      "StStMuMcTrack"
   };

   // Set Active braches
   for (const auto& branchName : activeBranchNames)
      maker->SetStatus(branchName.c_str(), 1);

   TChain *tree = maker->chain();
   Long64_t nentries = tree->GetEntries();
   nevent = TMath::Min(nevent, nentries);
   std::cout << nentries << " events in chain " << nevent << " will be read." << std::endl;
   tree->SetCacheSize(-1);        //by setting the read cache to -1 we set it to the AutoFlush value when writing
   tree->SetCacheLearnEntries(1); //one entry is sufficient to learn
   tree->SetCacheEntryRange(0, nevent);

   for (Long64_t ev = 0; ev < nevent; ev++) {
      if (maker->Make()) break;

      StMuDst *muDst = maker->muDst();   // get a pointer to the StMuDst class, the class that points to all the data
      StMuEvent *muEvent = muDst->event(); // get a pointer to the class holding event-wise information
      int referenceMultiplicity = muEvent->refMult(); // get the reference multiplicity

      TClonesArray *PrimaryVertices   = muDst->primaryVertices();
      int nPrimaryVertices = PrimaryVertices->GetEntriesFast();

      TClonesArray *MuMcVertices   = muDst->mcArray(0);
      int nMuMcVertices = MuMcVertices->GetEntriesFast();

      TClonesArray *MuMcTracks     = muDst->mcArray(1);
      int nMuMcTracks = MuMcTracks->GetEntriesFast();

      if ( nevent >= 10 && ev % int(nevent*0.1) == 0 )
      {
         std::cout << "Event #" << ev << "\tRun\t" << muEvent->runId()
                   << "\tId: " << muEvent->eventId()
                   << " refMult= " << referenceMultiplicity
                   << "\tPrimaryVertices " << nPrimaryVertices
                   << "\t" << " " << nMuMcVertices
                   << "\t" << " " << nMuMcTracks
                   << std::endl;
      }

      //    const Double_t field = muEvent->magneticField()*kilogauss;
      if (! nMuMcVertices || ! nMuMcTracks || nPrimaryVertices <= 0) {
         std::cout << "Ev. " << ev << " has no MC information ==> skip it" << std::endl;
         std::cout << "OR no reconstructed verticies found" << std::endl;
         continue;
      }

      // Count number of MC tracks at a vertex with TPC reconstructable tracks
      std::multimap<int, int> Mc2McHitTracks;

      for (int m = 0; m < nMuMcTracks; m++) {
         StMuMcTrack *McTrack = (StMuMcTrack *) MuMcTracks->UncheckedAt(m);

         if (McTrack->No_tpc_hit() < 15) continue;

         Mc2McHitTracks.insert(std::pair<int, int>(McTrack->IdVx(), McTrack->Id()));
      }

      // This is the "reconstructable" track multiplicity
      int nMcTracksWithHits = Mc2McHitTracks.count(1);

      // Let's skip events in which we do not expect to reconstruct any tracks
      // (and thus vertex) from the primary vertex
      if (nMcTracksWithHits <= 0) continue;

      // This is our denominator histogram for efficiencies
      McRecMulT->Fill(nMcTracksWithHits);

      // =============  Build map between  Rc and Mc vertices
      std::map<StMuPrimaryVertex *, StMuMcVertex *> reco2McVertices;
      TArrayF vertexRanks(nPrimaryVertices);
      int mcMatchedVertexIndex  = -1; // any vertex with MC==1 and highest reconstrated multiplicity.
      int vertexMaxMultiplicity = -1;

      // First loop over all verticies in this event. There is at least one
      // must be available
      for (int recoVertexIndex = 0; recoVertexIndex < nPrimaryVertices; recoVertexIndex++)
      {
         vertexRanks[recoVertexIndex] = -1e10;

         StMuPrimaryVertex *recoVertex = (StMuPrimaryVertex *) PrimaryVertices->UncheckedAt(recoVertexIndex);

         if ( !AcceptVX(recoVertex) ) continue;

         // Check Mc
         if (recoVertex->idTruth() < 0 || recoVertex->idTruth() > nMuMcVertices) {
            std::cout << "ERROR: Illegal idTruth " << recoVertex->idTruth() << " The track is ignored" << std::endl;
            continue;
         }

         StMuMcVertex *mcVertex = (StMuMcVertex *) MuMcVertices->UncheckedAt(recoVertex->idTruth() - 1);

         if (mcVertex->Id() != recoVertex->idTruth()) {
            std::cout << "ERROR: Mismatched idTruth " << recoVertex->idTruth() << " and mcVertex Id " <<  mcVertex->Id()
                 << " The vertex is ignored" <<  std::endl;
            continue;
         }

         reco2McVertices[recoVertex] = mcVertex;
         vertexRanks[recoVertexIndex] = recoVertex->ranking();

         if (recoVertex->idTruth() == 1 && recoVertex->noTracks() > vertexMaxMultiplicity)
         {
            mcMatchedVertexIndex  = recoVertexIndex;
            vertexMaxMultiplicity = recoVertex->noTracks();
         }

         FillData(data, recoVertex);

#ifdef __TMVA__
         Float_t *dataArray = &data.beam;

         for (size_t j = 0; j < inputVec->size(); j++)
            (*inputVec)[j] = dataArray[j];

         vertexRanks[recoVertexIndex] = classReader->GetMvaValue( *inputVec );
#endif
      }

      // If we reconstructed a vertex which matches the MC one we fill the
      // numerator of the "Any" efficiency histogram
      if (mcMatchedVertexIndex != -1) {

         StMuPrimaryVertex *recoVertexMatchedMc = (StMuPrimaryVertex*) PrimaryVertices->UncheckedAt(mcMatchedVertexIndex);

         double nTracks = recoVertexMatchedMc->noTracks();
         double nTracksQA = nTracks * recoVertexMatchedMc->qaTruth() / 100.;

         hists[0][0]->Fill(nMcTracksWithHits, nTracks);
         hists[0][1]->Fill(nMcTracksWithHits, nTracksQA);
         hists[0][2]->Fill(nMcTracksWithHits);
      }

      // Now deal with the highest rank vertex
      int maxRankVertexIndex = TMath::LocMax(nPrimaryVertices, vertexRanks.GetArray());

      StMuPrimaryVertex *recoVertexMaxRank = (StMuPrimaryVertex*) PrimaryVertices->UncheckedAt(maxRankVertexIndex);
      StMuMcVertex *mcVertex = reco2McVertices[recoVertexMaxRank];

      double nTracks = recoVertexMaxRank->noTracks();
      double nTracksQA = nTracks * recoVertexMaxRank->qaTruth() / 100.;

      // Fill numerator for "good" and "bad" efficiencies
      int h = ( mcVertex && mcVertex->Id() == 1) ? 1 : 2;

      hists[h][0]->Fill(nMcTracksWithHits, nTracks);
      hists[h][1]->Fill(nMcTracksWithHits, nTracksQA);
      hists[h][2]->Fill(nMcTracksWithHits);


      // Proceed with filling ntuple only if requested by the user
      if ( !fillNtuple ) continue;


      // Second loop over all verticies in this event
      for (int recoVertexIndex = 0; recoVertexIndex < nPrimaryVertices; recoVertexIndex++)
      {
         StMuPrimaryVertex *recoVertex = (StMuPrimaryVertex *) PrimaryVertices->UncheckedAt(recoVertexIndex);

         if ( !AcceptVX(recoVertex) ) continue;

         StMuMcVertex *mcVertex = reco2McVertices[recoVertex];

         if ( !mcVertex ) {
            std::cout << "No Match from RC to MC" << std::endl;
            continue;
         }

         if (vtxeval::gDebugFlag) {
            std::cout << Form("Vx[%3i]", recoVertexIndex) << *recoVertex << " " << *mcVertex;
            int nMcTracksWithHitsatL = Mc2McHitTracks.count(recoVertex->idTruth());
            std::cout << Form("Number of McTkHit %4i rank %8.3f", nMcTracksWithHitsatL, vertexRanks[recoVertexIndex]);
         }

         int IdPar = mcVertex->IdParTrk();

         if (IdPar > 0 && IdPar <= nMuMcTracks) {
            StMuMcTrack *mcTrack = (StMuMcTrack *) MuMcTracks->UncheckedAt(IdPar - 1);

            if (mcTrack && vtxeval::gDebugFlag) std::cout << " " << mcTrack->GeName();
         }

         FillData(data, recoVertex);

         double nTracks = recoVertex->noTracks();

         if (mcVertex->Id() == 1 && nTracks == vertexMaxMultiplicity) {// good
            VertexG->Fill(&data.beam);
         }
         else {   // bad
            VertexB->Fill(&data.beam);
         }
      }

      if ( !gROOT->IsBatch() ) {
         if (vtxeval::ask_user()) return;
      }
      else { vtxeval::gDebugFlag = false; }
   }

   fOut->Write();
}
Example #3
0
void makeMuDstQA(TString InputFileList, Int_t nFiles, Int_t nEvents, TString OutputDir ) 
{
 
  // Load libraries for CINT mode
#ifdef __CINT__
  gROOT   -> Macro("loadMuDst.C");
#endif

  // List of member links in the chain
  StChain*                    chain  =  new StChain ;

  StMuDstMaker*          muDstMaker  =  new StMuDstMaker(0,0,"",InputFileList,"MuDst",nFiles) ;

  // ---------------- modify here according to your QA purpose --------------------------
  // Turn off everything but Primary tracks in order to speed up the analysis and eliminate IO
  muDstMaker -> SetStatus("*",0) ;               // Turn off all branches
  muDstMaker -> SetStatus("MuEvent",1) ;         // Turn on the Event data (esp. Event number)
  muDstMaker -> SetStatus("PrimaryVertices",1) ;    // Turn on the primary track data
  muDstMaker -> SetStatus("PrimaryTracks",1) ;    // Turn on the primary track data
  muDstMaker -> SetStatus("GlobalTracks",1) ;    // Turn on the global track data
  muDstMaker -> SetStatus("CovGlobTrack",1);   // to fix the refmult in Run14!!!
  muDstMaker -> SetStatus("BTofHeader",1) ;    // Turn on the btof data
  muDstMaker -> SetDebug(0) ;                    // Turn off Debug information

  if ( nEvents == 0 )  nEvents = 10000000 ;       // Take all events in nFiles if nEvents = 0

  // ---------------- modify here according to your QA purpose --------------------------
  //book histograms or trees if you need
  TString oFile(muDstMaker->GetFile());
  TString oChopFile;
  int fileBeginIndex = oFile.Index("st_",0);
  oFile.Remove(0,fileBeginIndex);
  short indx1 = oFile.First('.');
  short indx2 = oFile.Last('.');
  if (indx1!=indx2) oFile.Remove(indx1+1,(indx2-indx1));
  oChopFile=oFile;
  oFile.Insert(indx1+1,"moretags.");
  oFile.Prepend(OutputDir);
  oChopFile.Insert(indx1+1,"chopper.");
  oChopFile.ReplaceAll("root","txt");
  oChopFile.Prepend(OutputDir);

  ofstream chop_output(oChopFile);

  TFile *tags_output = new TFile( oFile, "recreate" ) ;
  tags_output->cd();

  //TH1F *hPhi = new TH1F("hPhi","Phi of proton",200,-TMath::Pi(),TMath::Pi());
  //TH2F *hPhiFirstZ = new TH2F("hPhiFirstZ","Phi vs. FirstZ",200,-150,150,200,-TMath::Pi(),TMath::Pi()); 

  //Prepare the output tree
  Int_t mRunId, mEvtId;
  Int_t mnRefMult, mngRefMult, mnTofMatch;
  Float_t mVX, mVY, mVZ;
  Float_t mVpdVz;
  Float_t mPVRank;
  TTree *mMoreTagsTree = new TTree("MoreTags","MoreTags");
  mMoreTagsTree->Branch("RunId",&mRunId,"RunId/I");
  mMoreTagsTree->Branch("EvtId",&mEvtId,"EvtId/I");
  mMoreTagsTree->Branch("nRefMult",&mnRefMult,"nRefMult/I");
  mMoreTagsTree->Branch("ngRefMult",&mngRefMult,"ngRefMult/I");
  mMoreTagsTree->Branch("nTofMatch",&mnTofMatch,"nTofMatch/I");
  mMoreTagsTree->Branch("VX",&mVX,"VX/F");
  mMoreTagsTree->Branch("VY",&mVY,"VY/F");
  mMoreTagsTree->Branch("VZ",&mVZ,"VZ/F");
  mMoreTagsTree->Branch("VpdVz",&mVpdVz,"VpdVz/F");
  mMoreTagsTree->Branch("PVRank",&mPVRank,"PVRank/F");
  mMoreTagsTree->SetAutoSave(10000000);

  
  // ---------------- end of histogram and tree booking --------------------------------

  // Loop over the links in the chain
  Int_t iInit = chain -> Init() ;
  if (iInit) chain->FatalErr(iInit,"on init");
  
  // chain -> EventLoop(1,nEvents) ;  //will output lots of useless debugging info.
  Int_t istat = 0, i = 1;
  while (i <= nEvents && istat != 2) {
     if(i%10==0)cout << endl << "== Event " << i << " start ==" << endl;
     chain->Clear();
     istat = chain->Make(i);

     if (istat == 2)
	  cout << "Last  event processed. Status = " << istat << endl;
     if (istat == 3)
	  cout << "Error event processed. Status = " << istat << endl;
     i++;

     if(istat != kStOK)continue; //skip those suspectible events
     
  // ---------------- modify here according to your QA purpose --------------------------
     //let's do the QA here...
     //start with event cutting...
     //cout<<"In event #. "<<i-1<<" Maker status "<<istat<<endl;

     StMuDst* mMuDst = muDstMaker->muDst();
     if(!mMuDst) {
	  LOG_WARN << " No MuDst " << endm; continue;
     }

     StMuEvent* mMuEvent = mMuDst->event();
     if(!mMuEvent) {
	  LOG_WARN << " No MuEvent " << endm; continue;
     }

     //vzVpd
     StBTofHeader const* mBTofHeader = mMuDst->btofHeader();
     Float_t vzVpd=-999;
     if (mBTofHeader) vzVpd = mBTofHeader->vpdVz();

/*
     //Run14 vertex selection
     //////////////////////////////////////
     // select the right vertex using VPD
     /////////////////////////////////////
     for(unsigned int i=0;i<mMuDst->numberOfPrimaryVertices();i++) {
	  StMuPrimaryVertex *vtx = mMuDst->primaryVertex(i);
	  if(!vtx) continue;
	  Float_t vz = vtx->position().z();
	  if(fabs(vzVpd)<100 && fabs(vzVpd-vz)<3.) {
	     mMuDst->setVertexIndex(i);
	     break;
	  }
     }
     /////////////////////////////////////
*/

/*
     //Run16 vertex selection
     ////////////////////////////////////////////////////////////////
     if (fabs(vzVpd) < 200)
     {
	  for (unsigned int iVtx = 0; iVtx < mMuDst->numberOfPrimaryVertices(); ++iVtx)
	  {
	     StMuPrimaryVertex* vtx = mMuDst->primaryVertex(iVtx);
	     if (!vtx) continue;

	     if (fabs(vzVpd - vtx->position().z()) < 3.)
	     {
		  mMuDst->setVertexIndex(iVtx);
		  break;
	     }
	  }
     }
     ////////////////////////////////////////////////////////////////
*/

/*
     //Run15 pAu & Run16 dAu vertex selection
     int index = 0;
     const double mTpcVpdVzDiffCut = 6;
     if (mBTofHeader && fabs(vzVpd) < 200) {
	  for (unsigned int iVtx = 0; iVtx < mMuDst->numberOfPrimaryVertices(); ++iVtx) {
	     StMuPrimaryVertex* vtx = mMuDst->primaryVertex(iVtx);
	     if (!vtx) continue;
	     if (fabs(vzVpd - vtx->position().z()) < mTpcVpdVzDiffCut) {
		  index = iVtx;
		  break;
	     }
	  }
     }
     if(index>=0) mMuDst->setVertexIndex(index);
*/

     mRunId = mMuEvent->runNumber();
     mEvtId = mMuEvent->eventNumber();
     mnRefMult = mMuEvent->refMult();

     Int_t nTofMatPrTrack = 0;
     TObjArray* prtracks = muDstMaker->muDst()->primaryTracks() ;    // Create a TObject array containing the global tracks  
     TObjArrayIter GetPrTracks(prtracks) ;                              // Create an iterator to step through the tracks  
     StMuTrack* prtrack ;                                             // Pointer to a track
     while ( ( prtrack = (StMuTrack*)GetPrTracks.Next() ) )             // Main loop for Iterating over tracks
     {
	  if(prtrack->btofPidTraits().matchFlag()) nTofMatPrTrack ++;
     }
     mnTofMatch = nTofMatPrTrack;

     mVX = mMuEvent->primaryVertexPosition().x();
     mVY = mMuEvent->primaryVertexPosition().y();
     mVZ = mMuEvent->primaryVertexPosition().z();

     mVpdVz = vzVpd;
     if(mMuDst->primaryVertex())mPVRank = mMuDst->primaryVertex()->ranking();
     else mPVRank = -1e9;

     Int_t nGlTrack = 0;
     TObjArray* gltracks = muDstMaker->muDst()->globalTracks() ;    // Create a TObject array containing the global tracks  
     TObjArrayIter GetGlTracks(gltracks) ;                              // Create an iterator to step through the tracks  
     StMuTrack* gltrack ;                                             // Pointer to a track
     while ( ( gltrack = (StMuTrack*)GetGlTracks.Next() ) )             // Main loop for Iterating over tracks
     {
	  if(fabs(gltrack->eta())>=0.5)continue;
	  if(gltrack->nHitsFit()<10)continue;
	  if(gltrack->dca().mag()>=3.0)continue;
	  nGlTrack++ ;
     }
     mngRefMult = nGlTrack;

     mMoreTagsTree->Fill();

     //Event info (for debug)
     //cout<<"Run#: "<<mMuEvent->runNumber()<<endl;
     //cout<<"Evt#: "<<mMuEvent->eventNumber()<<endl;
     //cout<<muDstMaker->muDst()->currentVertexIndex()<<endl;
     //cout<<"refmult: "<<mMuEvent->refMult()<<endl;

     //Event cuts (NO EVENT CUTS TILL HERE!)
     //trigger
     if ( ! mMuEvent->triggerIdCollection().nominal().isTrigger(410008) && ! mMuEvent->triggerIdCollection().nominal().isTrigger(410005) ) continue;
     //Vz
     if ( fabs(mMuEvent->primaryVertexPosition().z()) > 30.0 ) continue ;
     //Vr
     //if ( mMuEvent->primaryVertexPosition().perp() > 100.0 ) continue ;
     //VF failed (for some old dataset)
     //if ( fabs(mMuEvent->primaryVertexPosition().x()) < 1e-5 && fabs(mMuEvent->primaryVertexPosition().y()) < 1e-5 && fabs(mMuEvent->primaryVertexPosition().z()) < 1e-5 ) continue;

     chop_output<<mRunId<<'\t'<<mEvtId<<endl;
     
     /*
     //fill Event QA histograms
     TObjArray* tracks = muDstMaker->muDst()->primaryTracks() ;
     TObjArrayIter GetTracks(tracks) ;
     StMuTrack* gtrack ; 
     while ( ( gtrack = (StMuTrack*)GetTracks.Next() ) )
     {
	  //const StMuTrack * gtrack = track->globalTrack();
	  if(gtrack->nHits()<=15)continue;
	  if(gtrack->flag()<=0)continue;
	  if(abs(gtrack->charge())!=1) continue;
	  if(gtrack->pt()>0.5) continue;
	  if(fabs(gtrack->nSigmaProton())>2)continue;
	  hPhi->Fill(gtrack->phi());
	  hPhiFirstZ->Fill(gtrack->firstPoint().z(),gtrack->phi());
     }
     //end of the filling
     */
  }

  if (nEvents > 1) chain -> Finish() ;

  if(tags_output!=NULL) tags_output -> Write() ;
  if(tags_output!=NULL) tags_output -> Close() ;
  //flush(tags_output);
  delete tags_output;

  chop_output.close();
  // Cleanup
  delete chain ;
}