#include "StHbtMaker/Infrastructure/StHbtEvent.hh"
#include "StHbtMaker/Infrastructure/StHbtTrack.hh"
#include "StHbtMaker/Infrastructure/StHbtV0.hh"
#include "StHbtMaker/Infrastructure/StHbtXi.hh"
#include "StHbtMaker/Infrastructure/StHbtKink.hh"
#include "StHbtMaker/Base/StHbtTrackCut.h"
#include "StHbtMaker/Base/StHbtV0Cut.h"
#include "StHbtMaker/Base/StHbtXiCut.h"
#include "StHbtMaker/Base/StHbtKinkCut.h"
#include "PhysicalConstants.h"
#include "SystemOfUnits.h"

#ifdef __ROOT__
#include "StMuDSTMaker/COMMON/StMuDst.h"
#include "StMuDSTMaker/COMMON/StMuEvent.h"
#include "StMuDSTMaker/COMMON/StMuTrack.h"
#include "StMuDSTMaker/COMMON/StMuDebug.h"

#include "StHbtMaker/Infrastructure/StHbtTTreeEvent.h"
#include "StHbtMaker/Infrastructure/StHbtTTreeTrack.h"
#include "StHbtMaker/Infrastructure/StHbtTTreeV0.h"
#include "StHbtMaker/Infrastructure/StHbtTTreeXi.h"
#include "StHbtMaker/Infrastructure/StHbtTTreeKink.h"

#include "TMCParticle.h"
#endif

//________________
StHbtEvent::StHbtEvent(const StHbtTTreeEvent* ev) {
#ifdef STHBTDEBUG
  std::cout << "StHbtEvent::StHbtEvent(const StHbtTTreeEvent* ev)" << std::endl;
#endif
  mEventNumber = ev->mEventNumber;
  mRunNumber = ev->mRunNumber;
  mTpcNhits = ev->mTpcNhits;
  mNumberOfTracks = ev->mNumberOfTracks;
  mNumberOfGoodTracks = ev->mNumberOfGoodTracks;
  mCtbMultiplicity = (unsigned short) ev->mCtbMultiplicity;
  mZdcAdc[0] = (unsigned short) ev->mZdcAdc[0];
  mZdcAdc[1] = (unsigned short) ev->mZdcAdc[1];
  mUncorrectedNumberOfPositivePrimaries = ev->mUncorrectedNumberOfPositivePrimaries;
  mUncorrectedNumberOfNegativePrimaries = ev->mUncorrectedNumberOfNegativePrimaries;
  mReactionPlane[0] = ev->mReactionPlane[0];
  mReactionPlane[1] = ev->mReactionPlane[1];
  mReactionPlanePtWgt[0] = ev->mReactionPlanePtWgt[0];
  mReactionPlanePtWgt[1] = ev->mReactionPlanePtWgt[1];
  mPrimVertPos = StHbtThreeVector(ev->mVertexX,ev->mVertexY,ev->mVertexZ);
  mMagneticField = ev->mMagneticField;
  mCent9  = 0;     // added by nik
  mCent16 = 0;     // added by nik
  mIsSim  = false; // added by nik
  mCorrectedNumberOfPrimaries = 0;
  if (mMagneticField==0) {
#if STHBTDEBUG
    std::cout << "StHbtEvent::StHbtEvent(const StHbtTTreeEvent* ev) - mMagneticField=" << mMagneticField << std::endl;
#endif
    mMagneticField = 2.5;
    //    ev->SetMagneticField(mMagneticField);   commented-out by malisa 14nov01 - unneeded and caused compiler problems
    std::cout << "StHbtEvent::StHbtEvent(const StHbtTTreeEvent* ev) - B=0 in TTree! WARNING!! PROBABLY SCREWED-UP!!" << std::endl;
  }
  mTriggerWord = ev->mTriggerWord;
  mTriggerActionWord = ev->mTriggerActionWord;
  //  for (int i=0;i<4; i++) mL3TriggerAlgorithm[i] = ev->mL3TriggerAlgorithm[i];
  mL3TriggerAlgorithm[0] = ev->mL3TriggerAlgorithm;


  // create collections
  mV0Collection = new StHbtV0Collection();
  mXiCollection = new StHbtXiCollection();
  mKinkCollection = new StHbtKinkCollection();
  mTrackCollection = new StHbtTrackCollection();

  // copy track collection
  for ( unsigned int i=0; i <ev->mNtracks; i++) {
    StHbtTrack* trackCopy = new StHbtTrack(ev, (StHbtTTreeTrack*)ev->tracks()->UncheckedAt(i));
    mTrackCollection->push_back(trackCopy);
  }
  // copy v0 collection
  for ( unsigned int i=0; i<ev->mNv0s; i++) {
    StHbtV0* v0Copy = new StHbtV0(ev, (StHbtTTreeV0*)ev->v0s()->UncheckedAt(i));
    mV0Collection->push_back(v0Copy);
  }
  // copy xi collection
  for ( unsigned int i=0; i<ev->mNxis; i++) {
    StHbtXi* xiCopy = new StHbtXi(ev, (StHbtTTreeXi*)ev->xis()->UncheckedAt(i));
    mXiCollection->push_back(xiCopy);
  }
  // copy kink collection
  for ( unsigned int i=0; i <ev->mNkinks; i++) {
    StHbtKink* kinkCopy = new StHbtKink(ev, (StHbtTTreeKink*)ev->kinks()->UncheckedAt(i));
    mKinkCollection->push_back(kinkCopy);
  }
  std::cout << "StHbtEvent::StHbtEvent(const StHbtTTreeEvent* ev) - collections:"
	    << " " << mTrackCollection->size()
	    << "/" << mV0Collection->size()
	    << "/" << mXiCollection->size()
	    << "/" << mKinkCollection->size() << std::endl;
}

#ifdef __ROOT__
#include "StMuDSTMaker/COMMON/StMuDst.h"
#include "StMuDSTMaker/COMMON/StMuEvent.h"
#include "StMuDSTMaker/COMMON/StMuTrack.h"
#include "StMuDSTMaker/COMMON/StMuDebug.h"
#endif

//________________
StHbtEvent::StHbtEvent(const StMuDst* dst, int trackType) {
  DEBUGMESSAGE1("");

  //added by gnigmat
#ifdef STHBTDEBUG
  std::cout << "StHbtEvent::StHbtEvent(const StMuDst* dst, int trackType)"
	    << std::endl << "Processing" << std::endl;
#endif

  StMuEvent* ev = dst->event();
  mEventNumber = ev->eventNumber();
  mRunNumber = ev->runNumber();
  mTpcNhits = 0;
  mNumberOfTracks = ev->eventSummary().numberOfTracks();
  mNumberOfGoodTracks = ev->eventSummary().numberOfGoodTracks();
  mCtbMultiplicity = (unsigned int) ev->ctbMultiplicity();
  mZdcAdc[0] = (unsigned int) ev->zdcAdcAttentuatedSumWest();
  mZdcAdc[1] = (unsigned int) ev->zdcAdcAttentuatedSumEast();
  mUncorrectedNumberOfPositivePrimaries = ev->refMultPos();
  mUncorrectedNumberOfNegativePrimaries = ev->refMultNeg();
  mUncorrectedNumberOfPrimaries = ev->refMult();
  mCorrectedNumberOfPrimaries = 0;
  mReactionPlane[0] = 0;
  mReactionPlane[1] = 0;
  mReactionPlanePtWgt[0] = 0;
  mReactionPlanePtWgt[1] = 0;
  mPrimVertPos = ev->eventSummary().primaryVertexPosition();
  mMagneticField = ev->magneticField();
  mCent9  = 0;      // added by nik
  mCent16 = 0;      // added by nik
  mIsSim  = false;  // added by nik
  //added by gnigmat
  StRunInfo runInfo = ev->runInfo();
  mZdcCoincidenceRate = runInfo.zdcCoincidenceRate();
  mBbcCoincidenceRate = runInfo.bbcCoincidenceRate();

  mTriggerWord = ev->l0Trigger().triggerWord();
  mTriggerActionWord = ev->l0Trigger().triggerActionWord();

  //added by gnigmat
  StBTofHeader* tofHeader = dst->btofHeader();
  if(!tofHeader) { //Empty header protection
    mVpdVz = mPrimVertPos.z();
  }
  else { 
    mVpdVz = tofHeader->vpdVz();
  }

  // create collections
  mV0Collection = new StHbtV0Collection();
  mXiCollection = new StHbtXiCollection();
  mKinkCollection = new StHbtKinkCollection();
  mTrackCollection = new StHbtTrackCollection();

  // copy track collection
  TObjArray*  tracks=0;
  switch (trackType) {
  case 0: tracks = dst->globalTracks(); break;
  case 1: tracks = dst->primaryTracks(); break;
  default: DEBUGMESSAGE("don't know how to handle this track type");
  }

  if (tracks) {

    DEBUGVALUE2(trackType);
    int nTracks = tracks->GetEntries();
    DEBUGVALUE2(tracks->GetEntries());
    
    int nVertices = dst->numberOfPrimaryVertices();
    for(int iVert=0; iVert<nVertices; iVert++) {

      mPrimVert = dst->primaryVertex(iVert);
      if( (iVert != 0) || (mPrimVert->ranking() <= 0)) continue; //Should be done in reader!

      StThreeVectorF mVertPosition = mPrimVert->position();

      //A couple of standard bad event cuts
      if( fabs(mVertPosition.x()) < 1e-5 &&
	  fabs(mVertPosition.y()) < 1e-5 &&
	  fabs(mVertPosition.z()) < 1e-5 ) continue;
      if( fabs(mVertPosition.z()) > 70.) continue;

      //Track loop
      for(int i=0; i<nTracks; i++) {

        //Analog of the preloaded cut
	if(trackType == 0) { //global tracks

	  mMuTrack = dst->globalTracks(i);
	  if( mMuTrack->momentum().mag() < 0.1 ||
	      mMuTrack->momentum().mag() > 2.5 ||
	      fabs(mMuTrack->eta()) > 1.1 ||
	      mMuTrack->nHits() < 10 ||
	      mMuTrack->flag() <= 0 ||
	      mMuTrack->flag() >= 1000) {
	    continue;
	  }
	}
	else { //primary tracks: trackType == 1
	  mMuTrack = dst->primaryTracks(i);
	  if( mMuTrack->vertexIndex() != iVert || 
	      mMuTrack->momentum().mag() < 0.1 ||
	      mMuTrack->momentum().mag() > 2.5 ||
	      fabs(mMuTrack->eta()) > 1.1 ||
	      mMuTrack->nHits() < 10 ||
	      mMuTrack->flag() <= 0 ||
	      mMuTrack->flag() >= 1000 ||
	      mMuTrack->dcaGlobal().mag() >= 3. ) {
	    continue;
	  }
	}

        StHbtTrack* trackCopy = new StHbtTrack(dst, (StMuTrack*) tracks->UncheckedAt(i));
        mTrackCollection->push_back(trackCopy);
      } //for(int i=0; i<nTracks; i++)
    } //for(int iVert=0; iVert<nVertices; iVert++)
  } //if (tracks)

  StStrangeEvMuDst* strangeEvent = dst->strangeEvent();
  // copy v0 collection
  int nV0s = dst->v0s()->GetEntries();
  for ( int i=0; i<nV0s; i++) {
    dst->v0s(i)->SetEvent(strangeEvent);

    StHbtV0* v0Copy = new StHbtV0( *dst->v0s(i) );
    mV0Collection->push_back(v0Copy);
  }
  // copy xi collection
  int nXis = dst->xis()->GetEntries();
  for ( int i=0; i<nXis; i++) {
    dst->xis(i)->SetEvent(strangeEvent);
    StHbtXi* xiCopy = new StHbtXi( *dst->xis(i) );
    mXiCollection->push_back(xiCopy);
  }
//   // copy kink collection
//   int nKinks = dst->kinks()->GetEntries();
//   for ( unsigned int i=0; i <nKinks; i++) {
//     StHbtKink* kinkCopy = new StHbtKink( *dst->kinks(i) );
//     mKinkCollection->push_back(kinkCopy);
//   }

  //added by gnigmat - too much for the log
#ifdef STHBTDEBUG
  std::cout << "StHbtEvent::StHbtEvent(const StMuDst* dst, int trackType) - collections:"
	    << " " << mTrackCollection->size()
	    << "/" << mV0Collection->size()
	    << "/" << mXiCollection->size()
	    << "/" << mKinkCollection->size() << std::endl;
#endif
}

//________________
StHbtEvent::StHbtEvent(const StMuDst* dst, int trackType, bool readV0Daughters) {

  DEBUGMESSAGE1("");

  //added by gnigmat
#ifdef STHBTDEBUG
  std::cout << "StHbtEvent::StHbtEvent(const StMuDst* dst, int trackType, bool readV0Daughters)  --  " 
	    << std::endl;
#endif

  StMuEvent* ev = dst->event();
  mEventNumber = ev->eventNumber();
  mRunNumber = ev->runNumber();
  mTpcNhits = 0;
  mNumberOfTracks = ev->eventSummary().numberOfTracks();
  mNumberOfGoodTracks = ev->eventSummary().numberOfGoodTracks();
  mCtbMultiplicity = (unsigned short) ev->ctbMultiplicity();
  mZdcAdc[0] = (unsigned short) ev->zdcAdcAttentuatedSumWest();
  mZdcAdc[1] = (unsigned short) ev->zdcAdcAttentuatedSumEast();
  mUncorrectedNumberOfPositivePrimaries = ev->refMultPos();
  mUncorrectedNumberOfNegativePrimaries = ev->refMultNeg();
  mUncorrectedNumberOfPrimaries = ev->refMult();
  mCorrectedNumberOfPrimaries = 0;
  mReactionPlane[0] = 0;
  mReactionPlane[1] = 0;
  mReactionPlanePtWgt[0] = 0;
  mReactionPlanePtWgt[1] = 0;
  mPrimVertPos = ev->eventSummary().primaryVertexPosition();
  mMagneticField = ev->magneticField();
  mCent9  = 0;      // added by nik
  mCent16 = 0;      // added by nik
  mIsSim  = false;  // added by nik
  //added by gnigmat
  StRunInfo runInfo = ev->runInfo();
  mZdcCoincidenceRate = runInfo.zdcCoincidenceRate();
  mBbcCoincidenceRate = runInfo.bbcCoincidenceRate();

  mTriggerWord = ev->l0Trigger().triggerWord();
  mTriggerActionWord = ev->l0Trigger().triggerActionWord();

  //added by gnigmat
  StBTofHeader* tofHeader = dst->btofHeader();
  if(!tofHeader) { //Emtpy header protection
    mVpdVz = mPrimVertPos.z();
  }
  else {
    mVpdVz = tofHeader->vpdVz();
  }

  // create collections
  mV0Collection = new StHbtV0Collection();
  mXiCollection = new StHbtXiCollection();
  mKinkCollection = new StHbtKinkCollection();
  mTrackCollection = new StHbtTrackCollection();

  /*
  if(!mTrackStruct.mFirstTrackId.empty()) mTrackStruct.mFirstTrackId.clear();
  if(!mTrackStruct.mFirstTrackVect.empty()) !mTrackStruct.mFirstTrackVect.clear();
  if(!mTrackStruct.mSecondTrackId.empty()) mTrackStruct.mSecondTrackId.clear();
  if(!mTrackStruct.mSecondTrackVect.empty()) mTrackStruct.mSecondTrackVect.clear();
  */

  // copy track collection
  TObjArray* tracks=0;
  switch (trackType) {
    case 0: tracks = dst->globalTracks(); break;
    case 1: tracks = dst->primaryTracks(); break;
    default: DEBUGMESSAGE("don't know how to handle this track type");
  }

  /*
  float mInverseBeta = -999.;
  float mMassSqr = -999.;
  TLorentzVector mVect;
  if (tracks) {
    DEBUGVALUE2(trackType);
    int nTracks = tracks->GetEntries();
    DEBUGVALUE2(tracks->GetEntries());

    int nVertices = dst->numberOfPrimaryVertices();
    for(int iVert=0; iVert<nVertices; iVert++) {

      mPrimVert = dst->primaryVertex(iVert);
      if( (iVert != 0) || (mPrimVert->ranking() <= 0)) continue;

      StThreeVectorF mVertPosition = mPrimVert->position();
      if(TMath::Abs(mVertPosition.z()) > 80.) continue;
      if(TMath::Abs(mVertPosition.z() - mVpdVz) > 10.) continue;
      for(int i=0; i<nTracks; i++) {

        //Analog of the preloaded cut
        mPrimTrack = dst->primaryTracks(i);
        if( mPrimTrack->vertexIndex() != iVert ||
            mPrimTrack->momentum().mag() < 0.1 ||
            mPrimTrack->momentum().mag() > 2.5 ||
            mPrimTrack->pt() < 0.1 ||
            mPrimTrack->pt() > 2.5 ||
            TMath::Abs(mPrimTrack->eta()) > 1.5 ||
            mPrimTrack->nHits() < 10 ) continue;

        StHbtTrack* trackCopy = new StHbtTrack(dst, (StMuTrack*) tracks->UncheckedAt(i));
        mTrackCollection->push_back(trackCopy);

        //Selecting kaons for phi mesons
        mGlobTrack = dst->globalTracks(mPrimTrack->index2Global());
        if(mGlobTrack->btofPidTraits().beta() > 0) {
          mInverseBeta = 1./mGlobTrack->btofPidTraits().beta();
          mMassSqr = mPrimTrack->momentum().mag2() * (mInverseBeta*mInverseBeta - 1);
          if( (mMassSqr < 0.15) || (mMassSqr > 0.3) ) continue;
          mVect.SetPxPyPzE(mPrimTrack->momentum().x(),
                           mPrimTrack->momentum().y(),
                           mPrimTrack->momentum().z(),
                           ::sqrt(mPrimTrack->momentum().mag2()+M_KAON*M_KAON));

          if(mPrimTrack->charge() > 0) {
            mTrackStruct.mFirstTrackId.push_back(i);
            mTrackStruct.mFirstTrackVect.push_back(mVect);
          }
          else {
            mTrackStruct.mSecondTrackId.push_back(i);
            mTrackStruct.mSecondTrackVect.push_back(mVect);
          }
        }
        else if(TMath::Abs(mPrimTrack->nSigmaKaon()) <= 3.) {

          mVect.SetPxPyPzE(mPrimTrack->momentum().x(),
                           mPrimTrack->momentum().y(),
                           mPrimTrack->momentum().z(),
                           ::sqrt(mPrimTrack->momentum().mag2()+M_KAON*M_KAON));
          if(mPrimTrack->charge() > 0) {
            mTrackStruct.mFirstTrackId.push_back(i);
            mTrackStruct.mFirstTrackVect.push_back(mVect);
          }
          else {
            mTrackStruct.mSecondTrackId.push_back(i);
            mTrackStruct.mSecondTrackVect.push_back(mVect);
          }
        }

      } //for(int i=0; i<nTracks; i++)
    } //for(int iVert=0; iVert<nVertices; iVert++)
  }

  //Reconstructing of phi meson
  if( (mTrackStruct.mFirstTrackId.size() != 0) &&
      (mTrackStruct.mSecondTrackId.size() != 0) ) {

    TLorentzVector phiVect;
    StMuTrack* PosKaonTrack;
    StMuTrack* NegKaonTrack;
    mPrimVert = dst->primaryVertex(0);
    for(unsigned iter1 = 0; iter1<mTrackStruct.mFirstTrackId.size(); iter1++) {
      for(unsigned iter2 = 0; iter2<mTrackStruct.mSecondTrackId.size(); iter2++) {

        phiVect = mTrackStruct.mFirstTrackVect.at(iter1) +
                  mTrackStruct.mSecondTrackVect.at(iter2);

        //Skeep the phi if the reconstructed mass exceed 30 MeV/c^2 from the table mass
        if(TMath::Abs(phiVect.M()-M_PHI) > 0.030) continue;

        PosKaonTrack = dst->primaryTracks(mTrackStruct.mFirstTrackId.at(iter1));
        NegKaonTrack = dst->primaryTracks(mTrackStruct.mSecondTrackId.at(iter2));
        StHbtV0* phiV0 = new StHbtV0();

        //Add dca calculation between two daughters
        phiV0->SetdecayLengthV0(46.5e-13);
        phiV0->SetdecayVertexV0X(mPrimVert->position().x());
        phiV0->SetdecayVertexV0Y(mPrimVert->position().y());
        phiV0->SetdecayVertexV0Z(mPrimVert->position().z());

      } //for(unsigned iter2 = 0; iter2<mTrackStruct.mSecondTrackId.size(); iter2++)
    } //for(unsigned iter1 = 0; iter1<mTrackStruct.mFirstTrackId.size(); iter1++)
  }
*/

  StStrangeEvMuDst* strangeEvent = dst->strangeEvent();
  // copy v0 collection
  int nV0s = dst->v0s()->GetEntries();
  // to read V0 daugthers
  double *TrackToId;
  tracks = dst->globalTracks();
  int nTracks = tracks->GetEntries();
  TrackToId = (double*)malloc(sizeof(double)*nTracks);
  for ( int i=0; i<nTracks; i++) {
	StHbtTrack* trackCopy = new StHbtTrack(dst, (StMuTrack*) tracks->UncheckedAt(i));
	TrackToId[i] = trackCopy->TrackId();
	delete trackCopy;
  }
  for ( int i=0; i<nV0s; i++) {
    dst->v0s(i)->SetEvent(strangeEvent);
    StHbtV0* v0Copy = new StHbtV0( *dst->v0s(i) );
    // Gael 23 Sept 02 --beg
    // search for daughters....
    if (readV0Daughters){
      tracks = dst->globalTracks();
      int nTracks = tracks->GetEntries();
      int V0NegOk = 1;
      int V0PosOk = 1;

      for ( int j=0; j<nTracks; j++) {
	if (TrackToId[j]==v0Copy->idNeg()) {
	  V0NegOk = -1;
	  StHbtTrack* trackCopy = new StHbtTrack(dst, (StMuTrack*) tracks->UncheckedAt(j));
	  v0Copy->SetHelixNeg(trackCopy->Helix());
	  delete trackCopy;
	}
	if (TrackToId[j]==v0Copy->idPos()) {
	  V0PosOk = -1;
	  StHbtTrack* trackCopy = new StHbtTrack(dst, (StMuTrack*) tracks->UncheckedAt(j));
	  v0Copy->SetHelixPos(trackCopy->Helix());
	  delete trackCopy;
	}

 	if ((V0PosOk < 0) && (V0NegOk < 0)) {
 	  break;}
      }

      if ((V0PosOk < 0) != (V0NegOk < 0)) {
	std::cout << "!!! StHbtEvent::At least One V0 daughter is not found !!!"
		  << std::endl;
      }
      v0Copy->SetprimaryVertex(ev->eventSummary().primaryVertexPosition());
    }
    mV0Collection->push_back(v0Copy);
  }
  free(TrackToId); // Gael 23 Sept 02 --end


  // copy xi collection
  int nXis = dst->xis()->GetEntries();
  for ( int i=0; i<nXis; i++) {
    dst->xis(i)->SetEvent(strangeEvent);
    StHbtXi* xiCopy = new StHbtXi( *dst->xis(i) );
    mXiCollection->push_back(xiCopy);
  }
//   // copy kink collection
//   int nKinks = dst->kinks()->GetEntries();
//   for ( unsigned int i=0; i <nKinks; i++) {
//     StHbtKink* kinkCopy = new StHbtKink( *dst->kinks(i) );
//     mKinkCollection->push_back(kinkCopy);
//   }

  std::cout << "StHbtEvent::StHbtEvent(const StHbtTTreeEvent* ev) - collections:"
	    << " " << mTrackCollection->size()
	    << "/" << mV0Collection->size()
	    << "/" << mXiCollection->size()
	    << "/" << mKinkCollection->size() << std::endl;
}

//___________________
// end Gael addition 24 Sept 02
//___________________
StHbtEvent::StHbtEvent(){
  mPrimVertPos[0]=-999.0;
  mPrimVertPos[1]=-999.0;
  mPrimVertPos[2]=-999.0;
  mVpdVz = -999.;
  mTrackCollection = new StHbtTrackCollection;
  mV0Collection = new StHbtV0Collection;
  mXiCollection = new StHbtXiCollection;
  mKinkCollection = new StHbtKinkCollection;
  mMagneticField=0.0;
  mCent9  = -1;
  mCent16 = -1;
  mCorrectedNumberOfPrimaries = 0;
  mIsSim  = false;
}
//___________________
StHbtEvent::StHbtEvent(const StHbtEvent& ev, StHbtTrackCut* tCut, StHbtV0Cut* vCut, 
		       StHbtXiCut* xCut, StHbtKinkCut* kCut) { // copy constructor with track and v0 cuts
  //cout << "StHbtEvent::StHbtEvent(const StHbtEvent& ev, StHbtTrackCut* tCut, StHbtV0Cut* vCut, StHbtV0Cut* kCut)" << endl;
  mEventNumber = ev.mEventNumber;
  mRunNumber = ev.mRunNumber;
  mCtbMultiplicity = ev.mCtbMultiplicity;
  mZdcAdc[0] = ev.mZdcAdc[0];
  mZdcAdc[1] = ev.mZdcAdc[1];
  mTpcNhits = ev.mTpcNhits;
  mNumberOfTracks = ev.mNumberOfTracks;
  mNumberOfGoodTracks = ev.mNumberOfGoodTracks;
  mUncorrectedNumberOfPositivePrimaries = ev.mUncorrectedNumberOfPositivePrimaries;
  mUncorrectedNumberOfNegativePrimaries = ev.mUncorrectedNumberOfNegativePrimaries;
  mUncorrectedNumberOfPrimaries = ev.mUncorrectedNumberOfPrimaries;
  mReactionPlane[0] = ev.mReactionPlane[0];
  mReactionPlane[1] = ev.mReactionPlane[1];
  mReactionPlanePtWgt[0] = ev.mReactionPlanePtWgt[0];
  mReactionPlanePtWgt[1] = ev.mReactionPlanePtWgt[1];
  mPrimVertPos = ev.mPrimVertPos;
  mMagneticField= ev.mMagneticField;
  mTriggerWord = ev.mTriggerWord;
  mTriggerActionWord = ev.mTriggerActionWord;
  mCent9  = ev.mCent9;  // added by nik
  mCent16 = ev.mCent16; // added by nik
  mIsSim  = ev.mIsSim;  // added by nik
  mCorrectedNumberOfPrimaries = ev.mCorrectedNumberOfPrimaries;
  for ( int i=0; i<4; i++) mL3TriggerAlgorithm[i] = ev.mL3TriggerAlgorithm[i];

  //added by gnigmat
  mZdcCoincidenceRate = ev.mZdcCoincidenceRate;
  mBbcCoincidenceRate = ev.mBbcCoincidenceRate;

  // create collections
  mTrackCollection = new StHbtTrackCollection;
  mV0Collection = new StHbtV0Collection;
  mXiCollection = new StHbtXiCollection;
  mKinkCollection = new StHbtKinkCollection;
  // copy track collection
  for ( StHbtTrackIterator tIter=ev.mTrackCollection->begin(); tIter!=ev.mTrackCollection->end(); tIter++) {
    if ( !tCut || tCut->Pass(*tIter) ) {
      StHbtTrack* trackCopy = new StHbtTrack(**tIter);
      mTrackCollection->push_back(trackCopy);
    }
  }
  // copy v0 collection
  for ( StHbtV0Iterator vIter=ev.mV0Collection->begin(); vIter!=ev.mV0Collection->end(); vIter++) {
    if ( !vCut || vCut->Pass(*vIter) ) {
      StHbtV0* v0Copy = new StHbtV0(**vIter);
      mV0Collection->push_back(v0Copy);
    }
  }
  // copy xi collection
  for ( StHbtXiIterator xIter=ev.mXiCollection->begin(); xIter!=ev.mXiCollection->end(); xIter++) {
    if ( !xCut || xCut->Pass(*xIter) ) {
      StHbtXi* xiCopy = new StHbtXi(**xIter);
      mXiCollection->push_back(xiCopy);
    }
  }
  // copy kink collection
  for ( StHbtKinkIterator kIter=ev.mKinkCollection->begin(); kIter!=ev.mKinkCollection->end(); kIter++) {
    if ( !kCut || kCut->Pass(*kIter) ) {
      //cout << " kinkCut passed " << endl;
      StHbtKink* kinkCopy = new StHbtKink(**kIter);
      mKinkCollection->push_back(kinkCopy);
    }
  }
}
//___________________
StHbtEvent::~StHbtEvent(){
#ifdef STHBTDEBUG
  std::cout << " StHbtEvent::~StHbtEvent() " << std::endl;
#endif
  for (StHbtTrackIterator iter=mTrackCollection->begin();iter!=mTrackCollection->end();iter++){
    delete *iter;
  }
  mTrackCollection->clear();
  delete mTrackCollection;
  //must do the same for the V0 collection
  for (StHbtV0Iterator V0iter=mV0Collection->begin();V0iter!=mV0Collection->end();V0iter++){
    delete *V0iter;
  }
  //must do the same for the Xi collection
  for (StHbtXiIterator XiIter=mXiCollection->begin();XiIter!=mXiCollection->end();XiIter++){
    delete *XiIter;
  }
  mXiCollection->clear();
  delete mXiCollection;
  //must do the same for the Kink collection
  for (StHbtKinkIterator kinkIter=mKinkCollection->begin();kinkIter!=mKinkCollection->end();kinkIter++){
    delete *kinkIter;
  }
  mKinkCollection->clear();
  delete mKinkCollection;

  /*
  if(mPrimVert) {
    delete mPrimVert;
  }
  if(mPrimTrack) {
    delete mPrimTrack;
  }
  if(mGlobTrack) {
    delete mGlobTrack;
  }
  */
}
//___________________
void StHbtEvent::RotateZ(const double angle){

  StHbtTrackIterator iter;
  StHbtV0Iterator V0iter;

  StPhysicalHelixD helix;
  StHbtThreeVector p;
  StHbtThreeVector o;
  double c;

  mReactionPlane[0] += angle;
  mReactionPlanePtWgt[0] += angle;
  std::cout << " StHbtEvent::RotateZ(const double angle) - angle="
	    << angle << " rad    ";
  std::cout << angle / degree << " deg " << std::endl;
  for (iter=mTrackCollection->begin();iter!=mTrackCollection->end();iter++){
      p = (*iter)->P();    p.rotateZ(angle);  (*iter)->SetP(p);
      p= (*iter)->Helix().momentum(mMagneticField*kilogauss);
      o= (*iter)->Helix().origin();
      p.rotateZ(angle);
      o.rotateZ(angle);
      c= (*iter)->Helix().charge(mMagneticField*kilogauss);
      helix = StPhysicalHelixD(p,o,mMagneticField*kilogauss,c);
      (*iter)->SetHelix(helix);
  }
  for (V0iter=mV0Collection->begin();V0iter!=mV0Collection->end();V0iter++){
    p=(*V0iter)->decayVertexV0();  p.rotateX(angle);   (*V0iter)->SetdecayVertexV0(p);
    p=(*V0iter)->momV0();          p.rotateX(angle);   (*V0iter)->SetmomV0(p);
    p=(*V0iter)->momPos();         p.rotateX(angle);   (*V0iter)->SetmomPos(p);
    p=(*V0iter)->momNeg();         p.rotateX(angle);   (*V0iter)->SetmomNeg(p);
  }
}

//_________________
float StHbtEvent::ReactionPlane(const int& wgt) const {

  return (wgt) ? mReactionPlanePtWgt[0] : mReactionPlane[0];
}

//_________________
float StHbtEvent::ReactionPlaneError(const int& wgt) const{
  return ReactionPlaneSubEventDifference(wgt);
}

//_________________
float StHbtEvent::ReactionPlaneSubEventDifference(const int& wgt) const{
  return (wgt) ? mReactionPlanePtWgt[0] : mReactionPlane[0];
}

//_________________
void StHbtEvent::SetReactionPlane(const float& rp,const int& wgt) {
  (wgt) ? mReactionPlanePtWgt[0]=rp : mReactionPlane[0]=rp;
}

//_________________
void StHbtEvent::SetReactionPlaneError(const float& rp, const int& wgt) {
  SetReactionPlaneSubEventDifference(rp,wgt);
}

//_________________
void StHbtEvent::SetReactionPlaneSubEventDifference(const float& rp, const int& wgt) {
  (wgt) ? mReactionPlanePtWgt[1]=rp : mReactionPlane[1]=rp;
}
