int PHG4GenFitTrackProjection::process_event(PHCompositeNode *topNode) {
	if (verbosity > 1)
		cout << "PHG4GenFitTrackProjection::process_event -- entered" << endl;

	//---------------------------------
	// Get Objects off of the Node Tree
	//---------------------------------

	// Pull the reconstructed track information off the node tree...
	SvtxTrackMap* _g4tracks = findNode::getClass<SvtxTrackMap>(topNode,
			"SvtxTrackMap");
	if (!_g4tracks) {
		cerr << PHWHERE << " ERROR: Can't find SvtxTrackMap." << endl;
		return Fun4AllReturnCodes::ABORTRUN;
	}

	for (int i = 0; i < _num_cal_layers; ++i) {

		if (std::isnan(_cal_radii[i]))
			continue;

		if (verbosity > 1)
			cout << "Projecting tracks into: " << _cal_names[i] << endl;

		// pull the tower geometry
		string towergeonodename = "TOWERGEOM_" + _cal_names[i];
		RawTowerGeomContainer *towergeo = findNode::getClass<
				RawTowerGeomContainer>(topNode, towergeonodename.c_str());
		if (!towergeo) {
			cerr << PHWHERE << " ERROR: Can't find node " << towergeonodename
					<< endl;
			return Fun4AllReturnCodes::ABORTRUN;
		}

		// pull the towers
		string towernodename = "TOWER_CALIB_" + _cal_names[i];
		RawTowerContainer *towerList = findNode::getClass<RawTowerContainer>(
				topNode, towernodename.c_str());
		if (!towerList) {
			cerr << PHWHERE << " ERROR: Can't find node " << towernodename
					<< endl;
			return Fun4AllReturnCodes::ABORTRUN;
		}

		// pull the clusters
		string clusternodename = "CLUSTER_" + _cal_names[i];
		RawClusterContainer *clusterList = findNode::getClass<
				RawClusterContainer>(topNode, clusternodename.c_str());
		if (!clusterList) {
			cerr << PHWHERE << " ERROR: Can't find node " << clusternodename
					<< endl;
			return Fun4AllReturnCodes::ABORTRUN;
		}

		// loop over all tracks
		for (SvtxTrackMap::Iter iter = _g4tracks->begin();
				iter != _g4tracks->end(); ++iter) {
			SvtxTrack *track = iter->second;
#ifdef DEBUG
			cout
			<<__LINE__
			<<": track->get_charge(): "<<track->get_charge()
			<<endl;
#endif
			if(!track) {
				if(verbosity >= 2) LogWarning("!track");
				continue;
			}

			if (verbosity > 1)
				cout << "projecting track id " << track->get_id() << endl;

			if (verbosity > 1) {
				cout << " track pt = " << track->get_pt() << endl;
			}

			std::vector<double> point;
			point.assign(3, -9999.);

			auto last_state_iter = --track->end_states();

			SvtxTrackState * trackstate = last_state_iter->second;

			if(!trackstate) {
				if(verbosity >= 2) LogWarning("!trackstate");
				continue;
			}

			auto pdg = unique_ptr<TDatabasePDG> (TDatabasePDG::Instance());
			int reco_charge = track->get_charge();
			int gues_charge = pdg->GetParticle(_pid_guess)->Charge();
			if(reco_charge*gues_charge<0) _pid_guess *= -1;
#ifdef DEBUG
			cout
			<<__LINE__
			<<": guess charge: " << gues_charge
			<<": reco charge: " << reco_charge
			<<": pid: " << _pid_guess
			<<": pT: " << sqrt(trackstate->get_px()*trackstate->get_px() + trackstate->get_py()*trackstate->get_py())
			<<endl;
#endif

			auto rep = unique_ptr<genfit::AbsTrackRep> (new genfit::RKTrackRep(_pid_guess));

			unique_ptr<genfit::MeasuredStateOnPlane> msop80 = nullptr;

			{
				TVector3 pos(trackstate->get_x(), trackstate->get_y(), trackstate->get_z());
				//pos.SetXYZ(0.01,0,0);

				TVector3 mom(trackstate->get_px(), trackstate->get_py(), trackstate->get_pz());
				//mom.SetXYZ(1,0,0);

				TMatrixDSym cov(6);
				for (int i = 0; i < 6; ++i) {
					for (int j = 0; j < 6; ++j) {
						cov[i][j] = trackstate->get_error(i, j);
					}
				}

				msop80 = unique_ptr<genfit::MeasuredStateOnPlane> (new genfit::MeasuredStateOnPlane(rep.get()));

				msop80->setPosMomCov(pos, mom, cov);
			}

#ifdef DEBUG
			{
				double x = msop80->getPos().X();
				double y = msop80->getPos().Y();
				double z = msop80->getPos().Z();
//				double px = msop80->getMom().X();
//				double py = msop80->getMom().Y();
				double pz = msop80->getMom().Z();
				genfit::FieldManager *field_mgr = genfit::FieldManager::getInstance();
				double Bx=0, By=0, Bz=0;
				field_mgr->getFieldVal(x,y,z,Bx,By,Bz);
				cout
				<< __LINE__
				<< ": { " << msop80->getPos().Perp() << ", " << msop80->getPos().Phi() << ", " << msop80->getPos().Eta() << "} @ "
				//<< "{ " << Bx << ", " << By << ", " << Bz << "}"
				<< "{ " << msop80->getMom().Perp() << ", " << msop80->getMom().Phi() << ", " << pz << "} "
				<<endl;
				//msop80->Print();
			}
#endif
			try {
				rep->extrapolateToCylinder(*msop80, _cal_radii[i], TVector3(0,0,0),  TVector3(0,0,1));
				//rep->extrapolateToCylinder(*msop80, 5., TVector3(0,0,0),  TVector3(0,0,1));
			} catch (...) {
				if(verbosity >= 2) LogWarning("extrapolateToCylinder failed");
				continue;
			}

#ifdef DEBUG
			{
				cout<<__LINE__<<endl;
				//msop80->Print();
				double x = msop80->getPos().X();
				double y = msop80->getPos().Y();
				double z = msop80->getPos().Z();
//				double px = msop80->getMom().X();
//				double py = msop80->getMom().Y();
				double pz = msop80->getMom().Z();
				genfit::FieldManager *field_mgr = genfit::FieldManager::getInstance();
				double Bx=0, By=0, Bz=0;
				field_mgr->getFieldVal(x,y,z,Bx,By,Bz);
				cout
				<< __LINE__
				<< ": { " << msop80->getPos().Perp() << ", " << msop80->getPos().Phi() << ", " << msop80->getPos().Eta() << "} @ "
				//<< "{ " << Bx << ", " << By << ", " << Bz << "}"
				<< "{ " << msop80->getMom().Perp() << ", " << msop80->getMom().Phi() << ", " << pz << "} "
				<<endl;
			}
#endif

			point[0] = msop80->getPos().X();
			point[1] = msop80->getPos().Y();
			point[2] = msop80->getPos().Z();

#ifdef DEBUG
			cout
			<<__LINE__
			<<": GenFit: {"
			<< point[0] <<", "
			<< point[1] <<", "
			<< point[2] <<" }"
			<<endl;
#endif

			if (std::isnan(point[0]))
				continue;
			if (std::isnan(point[1]))
				continue;
			if (std::isnan(point[2]))
				continue;

			double x = point[0];
			double y = point[1];
			double z = point[2];

			double phi = atan2(y, x);
			double eta = asinh(z / sqrt(x * x + y * y));

			if (verbosity > 1) {
				cout << " initial track phi = " << track->get_phi();
				cout << ", eta = " << track->get_eta() << endl;
				cout << " calorimeter phi = " << phi << ", eta = " << eta
						<< endl;
			}

			// projection is outside the detector extent
			// TODO towergeo doesn't make this easy to extract, but this should be
			// fetched from the node tree instead of hardcoded
			if (fabs(eta) >= 1.0)
				continue;

			// calculate 3x3 tower energy
			int binphi = towergeo->get_phibin(phi);
			int bineta = towergeo->get_etabin(eta);

			double energy_3x3 = 0.0;
			double energy_5x5 = 0.0;
			for (int iphi = binphi - 2; iphi <= binphi + 2; ++iphi) {
				for (int ieta = bineta - 2; ieta <= bineta + 2; ++ieta) {

					// wrap around
					int wrapphi = iphi;
					if (wrapphi < 0) {
						wrapphi = towergeo->get_phibins() + wrapphi;
					}
					if (wrapphi >= towergeo->get_phibins()) {
						wrapphi = wrapphi - towergeo->get_phibins();
					}

					// edges
					if (ieta < 0)
						continue;
					if (ieta >= towergeo->get_etabins())
						continue;

					RawTower* tower = towerList->getTower(ieta, wrapphi);
					if (tower) {

						energy_5x5 += tower->get_energy();
						if (abs(iphi - binphi) <= 1 and abs(ieta - bineta) <= 1)
							energy_3x3 += tower->get_energy();

						if (verbosity > 1)
							cout << " tower " << ieta << " " << wrapphi
									<< " energy = " << tower->get_energy()
									<< endl;
					}
				}
			}

			track->set_cal_energy_3x3(_cal_types[i], energy_3x3);
			track->set_cal_energy_5x5(_cal_types[i], energy_5x5);

			// loop over all clusters and find nearest
			double min_r = DBL_MAX;
			double min_index = -9999;
			double min_dphi = NAN;
			double min_deta = NAN;
			double min_e = NAN;
#ifdef DEBUG
			double min_cluster_phi = NAN;
#endif
			for (unsigned int k = 0; k < clusterList->size(); ++k) {

				RawCluster *cluster = clusterList->getCluster(k);

				double dphi = atan2(sin(phi - cluster->get_phi()),
						cos(phi - cluster->get_phi()));
				double deta = eta - cluster->get_eta();
				double r = sqrt(pow(dphi, 2) + pow(deta, 2));

				if (r < min_r) {
					min_index = k;
					min_r = r;
					min_dphi = dphi;
					min_deta = deta;
					min_e = cluster->get_energy();
#ifdef DEBUG
					min_cluster_phi = cluster->get_phi();
#endif
				}
			}

			if (min_index != -9999) {
				track->set_cal_dphi(_cal_types[i], min_dphi);
				track->set_cal_deta(_cal_types[i], min_deta);
				track->set_cal_cluster_id(_cal_types[i], min_index);
				track->set_cal_cluster_e(_cal_types[i], min_e);

#ifdef DEBUG
			cout
			<<__LINE__
			<<": min_cluster_phi: "<<min_cluster_phi
			<<endl;
#endif

				if (verbosity > 1) {
					cout << " nearest cluster dphi = " << min_dphi << " deta = "
							<< min_deta << " e = " << min_e << endl;
				}
			}

		} // end track loop
	} // end calorimeter layer loop

	if (verbosity > 1)
		cout << "PHG4GenFitTrackProjection::process_event -- exited" << endl;

	return Fun4AllReturnCodes::EVENT_OK;
}
int PHG4SvtxTrackProjection::process_event(PHCompositeNode *topNode)
{
  if(verbosity > 1) cout << "PHG4SvtxTrackProjection::process_event -- entered" << endl;

  //---------------------------------
  // Get Objects off of the Node Tree
  //---------------------------------

  // Pull the reconstructed track information off the node tree...
  SvtxTrackMap* _g4tracks = findNode::getClass<SvtxTrackMap>(topNode, "SvtxTrackMap");
  if (!_g4tracks) {
    cerr << PHWHERE << " ERROR: Can't find SvtxTrackMap." << endl;
    return Fun4AllReturnCodes::ABORTRUN;
  }

  for (int i=0;i<_num_cal_layers;++i) {

    if (isnan(_cal_radii[i])) continue;

    if (verbosity > 1) cout << "Projecting tracks into: " << _cal_names[i] << endl;

    // pull the tower geometry
    string towergeonodename = "TOWERGEOM_" + _cal_names[i];
    RawTowerGeom *towergeo = findNode::getClass<RawTowerGeom>(topNode,towergeonodename.c_str());
    if (!towergeo) {
      cerr << PHWHERE << " ERROR: Can't find node " << towergeonodename << endl;
      return Fun4AllReturnCodes::ABORTRUN;
    }

    // pull the towers
    string towernodename = "TOWER_CALIB_" + _cal_names[i];
    RawTowerContainer *towerList = findNode::getClass<RawTowerContainer>(topNode,towernodename.c_str());
    if (!towerList) {
      cerr << PHWHERE << " ERROR: Can't find node " << towernodename << endl;
      return Fun4AllReturnCodes::ABORTRUN;
    }

    // pull the clusters
    string clusternodename = "CLUSTER_" + _cal_names[i];
    RawClusterContainer *clusterList = findNode::getClass<RawClusterContainer>(topNode,clusternodename.c_str());
    if (!clusterList) {
      cerr << PHWHERE << " ERROR: Can't find node " << clusternodename << endl;
      return Fun4AllReturnCodes::ABORTRUN;
    }    
    
    // loop over all tracks
    for (SvtxTrackMap::Iter iter = _g4tracks->begin();
	 iter != _g4tracks->end();
	 ++iter) {
      SvtxTrack *track = iter->second;

      if (verbosity > 1) cout << "projecting track id " << track->get_id() << endl;

      if (verbosity > 1) {
	cout << " track pt = " << track->get_pt() << endl;
      }

      // curved tracks inside mag field
      // straight projections thereafter
      std::vector<double> point;
      point.assign(3,-9999.);
      //if (_cal_radii[i] < _mag_extent) {
      // curved projections inside field

      _hough.projectToRadius(track,_magfield,_cal_radii[i],point);

      if (isnan(point[0])) continue;
      if (isnan(point[1])) continue;
      if (isnan(point[2])) continue;
      // } else {
      // 	// straight line projections after mag field exit
      // 	_hough.projectToRadius(track,_mag_extent-0.05,point);
      // 	if (isnan(point[0])) continue;
      // 	if (isnan(point[1])) continue;
      // 	if (isnan(point[2])) continue;

      // 	std::vector<double> point2;
      // 	point2.assign(3,-9999.);
      // 	_hough.projectToRadius(track,_mag_extent+0.05,point2);
      // 	if (isnan(point2[0])) continue;
      // 	if (isnan(point2[1])) continue;
      // 	if (isnan(point2[2])) continue;

      // 	// find intersection of r and z


      // find x,y of intersection
      //}
      double x = point[0];
      double y = point[1];
      double z = point[2];

      double phi = atan2(y,x);
      double eta = asinh(z/sqrt(x*x+y*y));

      if (verbosity > 1) {
	cout << " initial track phi = " << track->get_phi();
	cout << ", eta = " << track->get_eta() << endl;
	cout << " calorimeter phi = " << phi << ", eta = " << eta << endl;
      }

      // projection is outside the detector extent
      // \todo towergeo doesn't make this easy to extract, but this should be
      // fetched from the node tree instead of hardcoded
      if (fabs(eta) >= 1.0) continue;

      // calculate 3x3 tower energy
      int binphi = towergeo->get_phibin(phi);
      int bineta = towergeo->get_etabin(eta);

      double energy_3x3 = 0.0;
      for (int iphi = binphi-1; iphi < binphi+2; ++iphi) { 
      	for (int ieta = bineta-1; ieta < bineta+2; ++ieta) { 

	  // wrap around
	  int wrapphi = iphi;
	  if (wrapphi < 0) {
	    wrapphi = towergeo->get_phibins() + wrapphi;
	  }
	  if (wrapphi >= towergeo->get_phibins()) {
	    wrapphi = wrapphi - towergeo->get_phibins();
	  }

	  // edges
	  if (ieta < 0) continue;
	  if (ieta >= towergeo->get_etabins()) continue;

	  RawTower* tower = towerList->getTower(ieta,wrapphi);
	  if (tower) {
	    energy_3x3 += tower->get_energy();

	    if (verbosity > 1) cout << " tower " << ieta << " " << wrapphi << " energy = " << tower->get_energy() << endl;
	  }
      	}
      }

      track->set_cal_energy_3x3(_cal_types[i],energy_3x3);

      // loop over all clusters and find nearest
      double min_r = DBL_MAX;
      double min_index = -9999;
      double min_dphi = NAN;
      double min_deta = NAN;
      double min_e = NAN;
      for (unsigned int k = 0; k < clusterList->size(); ++k) {

	RawCluster *cluster = clusterList->getCluster(k);

	double dphi = atan2(sin(phi-cluster->get_phi()),cos(phi-cluster->get_phi()));
	double deta = eta-cluster->get_eta();
	double r = sqrt(pow(dphi,2)+pow(deta,2));

	if (r < min_r) {
	  min_index = k;
	  min_r = r;
	  min_dphi = dphi;
	  min_deta = deta;
	  min_e = cluster->get_energy();
	}
      }

      if (min_index != -9999) {
	track->set_cal_dphi(_cal_types[i],min_dphi);
	track->set_cal_deta(_cal_types[i],min_deta);
	track->set_cal_cluster_id(_cal_types[i],min_index);
	track->set_cal_cluster_e(_cal_types[i],min_e);

	if (verbosity > 1) {
	  cout << " nearest cluster dphi = " << min_dphi << " deta = " << min_deta << " e = " << min_e << endl;
	}
      }

    } // end track loop
  } // end calorimeter layer loop

 
  if(verbosity > 1) cout << "PHG4SvtxTrackProjection::process_event -- exited" << endl;

  return Fun4AllReturnCodes::EVENT_OK;
}
RawCluster*
TrackProjectionTools::getCluster( SvtxTrack* track, string detName )
{
  /* track direction */
  float eta = 0;
  float phi = 0;

  /* closest cluster */
  RawCluster* cluster_min_dr = NULL;

  // pull the clusters
  string clusternodename = "CLUSTER_" + detName;
  RawClusterContainer *clusterList = findNode::getClass<RawClusterContainer>(_topNode,clusternodename.c_str());
  if (!clusterList) {
    cerr << PHWHERE << " ERROR: Can't find node " << clusternodename << endl;
    return NULL;
  }

  // loop over all clusters and find nearest
  double min_r = NAN;

  for (unsigned int k = 0; k < clusterList->size(); ++k) {

    RawCluster *cluster = clusterList->getCluster(k);

    double dphi = atan2(sin(phi-cluster->get_phi()),cos(phi-cluster->get_phi()));

    double cluster_theta = atan2( cluster->get_r() , cluster->get_z() );
    double cluster_eta =  -log(tan(cluster_theta/2.0));

    double deta = eta-cluster_eta;
    double r = sqrt(pow(dphi,2)+pow(deta,2));

    if (r < min_r) {
      min_r = r;
      cluster_min_dr = cluster;
    }
  }

//  if(detName == "FEMC") {
//    if(!secondFlag){
//      femc_cldr = min_r;
//      femc_clE = min_e;
//      femc_clN = min_n;
//    }
//    else{
//      femc_cldr2 = min_r;
//      femc_clE2 = min_e;
//      femc_clN2 = min_n;
//    }
//  }
//  else{
//    if(!secondFlag){
//      fhcal_cldr = min_r;
//      fhcal_clE = min_e;
//      fhcal_clN = min_n;
//    }
//    else{
//      fhcal_cldr2 = min_r;
//      fhcal_clE2 = min_e;
//      fhcal_clN2 = min_n;
//    }
//  }
//
  return cluster_min_dr;
}
Exemple #4
0
int PhotonJet::process_event(PHCompositeNode *topnode)
{
 
  cout<<"at event number "<<nevents<<endl;


  //get the nodes from the NodeTree
  JetMap* truth_jets = findNode::getClass<JetMap>(topnode,"AntiKt_Truth_r04");
  JetMap *reco_jets = findNode::getClass<JetMap>(topnode,"AntiKt_Tower_r04");
  PHG4TruthInfoContainer* truthinfo = findNode::getClass<PHG4TruthInfoContainer>(topnode,"G4TruthInfo");
  RawClusterContainer *clusters = findNode::getClass<RawClusterContainer>(topnode,"CLUSTER_CEMC");
  SvtxTrackMap *trackmap = findNode::getClass<SvtxTrackMap>(topnode,"SvtxTrackMap");
  JetEvalStack* _jetevalstack = new JetEvalStack(topnode,"AntiKt_Tower_r04","AntiKt_Truth_r04");
  PHG4TruthInfoContainer::Range range = truthinfo->GetPrimaryParticleRange();

  if(!truth_jets){
      cout<<"no truth jets"<<endl;
      return 0;
    }
  if(!reco_jets){
      cout<<"no reco jets"<<endl;
      return 0;
    }
  if(!truthinfo){
      cout<<"no truth track info"<<endl;
      return 0;
    }
  if(!clusters){
    cout<<"no cluster info"<<endl;
    return 0;
  }
  if(!trackmap){
    cout<<"no track map"<<endl;
    return 0;
  }
  if(!_jetevalstack){
    cout<<"no good truth jets"<<endl;
    return 0;
  }


  JetRecoEval* recoeval = _jetevalstack->get_reco_eval();


 /***********************************************

  GET THE TRUTH PARTICLES

  ************************************************/



  for( PHG4TruthInfoContainer::ConstIterator iter = range.first; iter!=range.second; ++iter){

    PHG4Particle *truth = iter->second;
    
    truthpx = truth->get_px();
    truthpy = truth->get_py();
    truthpz = truth->get_pz();
    truthp = sqrt(truthpx*truthpx+truthpy*truthpy+truthpz*truthpz);
    truthenergy = truth->get_e();
    
    TLorentzVector vec;
    vec.SetPxPyPzE(truthpx,truthpy,truthpz,truthenergy);
    
    truthpt = sqrt(truthpx*truthpx+truthpy*truthpy);
    if(truthpt<0.5)
      continue;
    
    truthphi = vec.Phi();
    trutheta = vec.Eta();
    truthpid = truth->get_pid();
    
    truth_g4particles->Fill();

  }


  /***********************************************

  GET THE EMCAL CLUSTERS

  ************************************************/


  RawClusterContainer::ConstRange begin_end = clusters->getClusters();
  RawClusterContainer::ConstIterator clusiter;
  
  for(clusiter = begin_end.first; clusiter!=begin_end.second; ++clusiter){

    RawCluster *cluster = clusiter->second;

    clus_energy = cluster->get_energy();
    clus_eta = cluster->get_eta();
    clus_theta = 2.*TMath::ATan((TMath::Exp(-1.*clus_eta)));
    clus_pt = clus_energy*TMath::Sin(clus_theta);
    clus_phi = cluster->get_phi();
    
    if(clus_pt<0.5)
      continue;

   
    
    TLorentzVector *clus = new TLorentzVector();
    clus->SetPtEtaPhiE(clus_pt,clus_eta,clus_phi,clus_energy);
    
    float dumarray[4];
    clus->GetXYZT(dumarray);
    clus_x = dumarray[0];
    clus_y = dumarray[1];
    clus_z = dumarray[2];
    clus_t = dumarray[3];

    clus_px = clus_pt*TMath::Cos(clus_phi);
    clus_py = clus_pt*TMath::Sin(clus_phi);
    clus_pz = sqrt(clus_energy*clus_energy-clus_px*clus_px-clus_py*clus_py);

    cluster_tree->Fill();

    //only interested in high pt photons to be isolated
    if(clus_pt<mincluspt)
      continue;
    if(fabs(clus_eta)>(1.0-isoconeradius))
      continue;

    float energysum = ConeSum(cluster,clusters,trackmap,isoconeradius);
    bool conecut = energysum > 0.1*clus_energy;
    if(conecut)
      continue;
   
    isolated_clusters->Fill();
    
    GetRecoHadronsAndJets(cluster, trackmap, reco_jets,recoeval);

  }



  /***********************************************

  GET THE SVTX TRACKS

  ************************************************/
  
  SvtxEvalStack *svtxevalstack = new SvtxEvalStack(topnode);
  svtxevalstack->next_event(topnode);

  SvtxTrackEval *trackeval = svtxevalstack->get_track_eval();

  for(SvtxTrackMap::Iter iter = trackmap->begin(); iter!=trackmap->end(); ++iter){

    SvtxTrack *track = iter->second;

    //get reco info
    tr_px = track->get_px();
    tr_py = track->get_py();
    tr_pz = track->get_pz();
    tr_p = sqrt(tr_px*tr_px+tr_py*tr_py+tr_pz*tr_pz);
    
    tr_pt = sqrt(tr_px*tr_px+tr_py*tr_py);
    
    if(tr_pt<0.5)
      continue;
  
    tr_phi = track->get_phi();
    tr_eta = track->get_eta();

    if(fabs(tr_eta)>1)
      continue;

    charge = track->get_charge();
    chisq = track->get_chisq();
    ndf = track->get_ndf();
    dca = track->get_dca();
    tr_x = track->get_x();
    tr_y = track->get_y();
    tr_z = track->get_z();
    
   
    //get truth info
    PHG4Particle *truthtrack = trackeval->max_truth_particle_by_nclusters(track);
    truth_is_primary = truthinfo->is_primary(truthtrack);
    
    truthtrackpx = truthtrack->get_px();
    truthtrackpy = truthtrack->get_py();
    truthtrackpz = truthtrack->get_pz();
    truthtrackp = sqrt(truthtrackpx*truthtrackpx+truthtrackpy*truthtrackpy+truthtrackpz*truthtrackpz);
    
    truthtracke = truthtrack->get_e();
    TLorentzVector *Truthtrack = new TLorentzVector();
    Truthtrack->SetPxPyPzE(truthtrackpx,truthtrackpy,truthtrackpz,truthtracke);
    truthtrackpt = Truthtrack->Pt();
    truthtrackphi = Truthtrack->Phi();
    truthtracketa = Truthtrack->Eta();
    truthtrackpid = truthtrack->get_pid();


    tracktree->Fill();

  }







  /***************************************

   TRUTH JETS

   ***************************************/


  for(JetMap::Iter iter = truth_jets->begin(); iter!=truth_jets->end(); ++iter){
    Jet *jet = iter->second;
    
    truthjetpt = jet->get_pt();
    if(truthjetpt<10.)
      continue;
    
    truthjeteta = jet->get_eta();
    if(fabs(truthjeteta)>2.)
      continue;

    truthjetpx = jet->get_px();
    truthjetpy = jet->get_py();
    truthjetpz = jet->get_pz();
    truthjetphi = jet->get_phi();
    truthjetmass = jet->get_mass();
    truthjetp = jet->get_p();
    truthjetenergy = jet->get_e();
    
    truthjettree->Fill();
    


  }



/***************************************

   RECONSTRUCTED JETS

   ***************************************/



  for(JetMap::Iter iter = reco_jets->begin(); iter!=reco_jets->end(); ++iter){
    Jet *jet = iter->second;
    Jet *truthjet = recoeval->max_truth_jet_by_energy(jet);
    recojetpt = jet->get_pt();
    if(recojetpt<4.)
      continue;
    
    recojeteta = jet->get_eta();
    if(fabs(recojeteta)>2.)
      continue;
    recojetid = jet->get_id();
    recojetpx = jet->get_px();
    recojetpy = jet->get_py();
    recojetpz = jet->get_pz();
    recojetphi = jet->get_phi();
    recojetmass = jet->get_mass();
    recojetp = jet->get_p();
    recojetenergy = jet->get_e();

    if(truthjet){
      truthjetid = truthjet->get_id();
      truthjetp = truthjet->get_p();
      truthjetphi = truthjet->get_phi();
      truthjeteta = truthjet->get_eta();
      truthjetpt = truthjet->get_pt();
      truthjetenergy = truthjet->get_e();
      truthjetpx = truthjet->get_px();
      truthjetpy = truthjet->get_py();
      truthjetpz = truthjet->get_pz();
    }
    else{
      truthjetid = 0;
      truthjetp = 0;
      truthjetphi = 0;
      truthjeteta = 0;
      truthjetpt = 0;
      truthjetenergy = 0;
      truthjetpx = 0;
      truthjetpy = 0;
      truthjetpz = 0;
      
    }
    recojettree->Fill();

  }

  


  nevents++;
  tree->Fill();
  return 0;

}
std::vector<Jet*> ClusterJetInput::get_input(PHCompositeNode *topNode) {
  
  if (_verbosity > 0) cout << "ClusterJetInput::process_event -- entered" << endl;

  GlobalVertexMap* vertexmap = findNode::getClass<GlobalVertexMap>(topNode,"GlobalVertexMap");
  if (!vertexmap) {
    return std::vector<Jet*>();
  }
  
  RawClusterContainer *clusters = NULL;
  RawTowerGeom *geom = NULL;
  if (_input == Jet::CEMC_CLUSTER) {
    clusters = findNode::getClass<RawClusterContainer>(topNode,"CLUSTER_CEMC");
    geom = findNode::getClass<RawTowerGeom>(topNode,"TOWERGEOM_CEMC");
    if (!clusters||!geom) {
      return std::vector<Jet*>();
    }
  } else if (_input == Jet::HCALIN_CLUSTER) {
    clusters = findNode::getClass<RawClusterContainer>(topNode,"CLUSTER_HCALIN");
    geom = findNode::getClass<RawTowerGeom>(topNode,"TOWERGEOM_HCALIN");
    if (!clusters||!geom) {
      return std::vector<Jet*>();
    }
  } else if (_input == Jet::HCALOUT_CLUSTER) {
    clusters = findNode::getClass<RawClusterContainer>(topNode,"CLUSTER_HCALOUT");
    geom = findNode::getClass<RawTowerGeom>(topNode,"TOWERGEOM_HCALOUT");
    if (!clusters||!geom) {
      return std::vector<Jet*>();
    }
  } else {
    return std::vector<Jet*>();
  }

  // first grab the event vertex or bail
  GlobalVertex* vtx = vertexmap->begin()->second;
  float vtxz = NAN;
  if (vtx) vtxz = vtx->get_z();
  else return std::vector<Jet*>();

  std::vector<Jet*> pseudojets;
  RawClusterContainer::ConstRange begin_end = clusters->getClusters();
  RawClusterContainer::ConstIterator rtiter;
  for (rtiter = begin_end.first; rtiter !=  begin_end.second; ++rtiter) {
    RawCluster *cluster = rtiter->second;

    double r = geom->get_radius();
    
    double eta0 = cluster->get_eta();
    double phi = cluster->get_phi();

    double z0 = r * sinh(eta0);
    double z = z0 - vtxz;
    
    double eta = asinh(z/r); // eta after shift from vertex
    
    double pt = cluster->get_energy() / cosh(eta);
    double px = pt * cos(phi);
    double py = pt * sin(phi);
    double pz = pt * sinh(eta);

    Jet *jet = new JetV1();
    jet->set_px(px);
    jet->set_py(py);
    jet->set_pz(pz);
    jet->set_e(cluster->get_energy());
    jet->insert_comp(_input,cluster->get_id());
    pseudojets.push_back(jet);
  }

  if (_verbosity > 0) cout << "ClusterJetInput::process_event -- exited" << endl;

  return pseudojets;
}
void CaloEvaluator::fillOutputNtuples(PHCompositeNode *topNode) {
  
  if (verbosity > 2) cout << "CaloEvaluator::fillOutputNtuples() entered" << endl;

  CaloRawClusterEval* clustereval = _caloevalstack->get_rawcluster_eval();
  CaloRawTowerEval*     towereval = _caloevalstack->get_rawtower_eval();
  CaloTruthEval*        trutheval = _caloevalstack->get_truth_eval();
  
  //----------------------
  // fill the Event NTuple
  //----------------------

  if (_do_gpoint_eval) {
    // need things off of the DST...
    PHG4TruthInfoContainer* truthinfo = findNode::getClass<PHG4TruthInfoContainer>(topNode,"G4TruthInfo");
    if (!truthinfo) {
      cerr << PHWHERE << " ERROR: Can't find G4TruthInfo" << endl;
      exit(-1);
    }

    // need things off of the DST...
    SvtxVertexMap* vertexmap = findNode::getClass<SvtxVertexMap>(topNode,"SvtxVertexMap");

    PHG4VtxPoint *gvertex = truthinfo->GetPrimaryVtx( truthinfo->GetPrimaryVertexIndex() );
    float gvx = gvertex->get_x();
    float gvy = gvertex->get_y();
    float gvz = gvertex->get_z();

    float vx = NAN;
    float vy = NAN;
    float vz = NAN;
    if (vertexmap) {
      if (!vertexmap->empty()) {
	SvtxVertex* vertex = (vertexmap->begin()->second);
	
	vx = vertex->get_x();
	vy = vertex->get_y();
	vz = vertex->get_z();
      }
    }
	
    float gpoint_data[7] = {_ievent,
			    gvx,
			    gvy,
			    gvz,
			    vx,
			    vy,
			    vz
    };

    _ntp_gpoint->Fill(gpoint_data);   
  }
  
  //------------------------
  // fill the Gshower NTuple
  //------------------------
  
  if (_ntp_gshower) {

    if (verbosity > 1) cout << "CaloEvaluator::filling gshower ntuple..." << endl;
    
    PHG4TruthInfoContainer* truthinfo = findNode::getClass<PHG4TruthInfoContainer>(topNode,"G4TruthInfo");   
    if (!truthinfo) {
      cerr << PHWHERE << " ERROR: Can't find G4TruthInfo" << endl;
      exit(-1);
    }

    PHG4TruthInfoContainer::ConstRange range = truthinfo->GetPrimaryParticleRange();
    for (PHG4TruthInfoContainer::ConstIterator iter = range.first;
	 iter != range.second; 
	 ++iter) {
    
      PHG4Particle* primary = iter->second;

      if (primary->get_e() < _truth_e_threshold) continue;
      
      if (!_truth_trace_embed_flags.empty()) {
	if (_truth_trace_embed_flags.find(trutheval->get_embed(primary)) ==
	    _truth_trace_embed_flags.end()) continue;
      }
      
      float gparticleID = primary->get_track_id();
      float gflavor     = primary->get_pid();
      
      std::set<PHG4Hit*> g4hits = trutheval->get_shower_from_primary(primary);     
      float gnhits   = g4hits.size();	
      float gpx      = primary->get_px();
      float gpy      = primary->get_py();
      float gpz      = primary->get_pz();
      float ge       = primary->get_e();

      float gpt = sqrt(gpx*gpx+gpy*gpy);
      float geta = NAN;
      if (gpt != 0.0) geta = asinh(gpz/gpt);
      float gphi = atan2(gpy,gpx);
      
      PHG4VtxPoint* vtx = trutheval->get_vertex(primary);	
      float gvx      = vtx->get_x();
      float gvy      = vtx->get_y();
      float gvz      = vtx->get_z();
      
      float gembed   = trutheval->get_embed(primary);
      float gedep    = trutheval->get_shower_energy_deposit(primary);
      float gmrad    = trutheval->get_shower_moliere_radius(primary);

      RawCluster* cluster = clustereval->best_cluster_from(primary);

      float clusterID = NAN;
      float ntowers   = NAN;
      float eta       = NAN;
      float phi       = NAN;
      float e         = NAN;
      
      float efromtruth     = NAN;

      if (cluster) {      
	clusterID = cluster->get_id();
	ntowers   = cluster->getNTowers();
	eta       = cluster->get_eta();
	phi       = cluster->get_phi();
	e         = cluster->get_energy();
	
	efromtruth     = clustereval->get_energy_contribution(cluster, primary);
      }
      
      float shower_data[20] = {_ievent,
			       gparticleID,
			       gflavor,
			       gnhits,
			       geta,
			       gphi,
			       ge,
			       gpt,
			       gvx,
			       gvy,
			       gvz,
			       gembed,
			       gedep,
			       gmrad,
			       clusterID,
			       ntowers,
			       eta,
			       phi,
			       e,
			       efromtruth
      };

      _ntp_gshower->Fill(shower_data);
    }
  }

  //----------------------
  // fill the Tower NTuple
  //----------------------
 
  if (_do_tower_eval) {

    if (verbosity > 1) cout << "CaloEvaluator::filling tower ntuple..." << endl;
    
    string towernode = "TOWER_CALIB_" + _caloname;
    RawTowerContainer* towers = findNode::getClass<RawTowerContainer>(topNode,towernode.c_str());
    if (!towers) {
      cerr << PHWHERE << " ERROR: Can't find " << towernode << endl;
      exit(-1);
    }
    
    string towergeomnode = "TOWERGEOM_" + _caloname;
    RawTowerGeomContainer* towergeom = findNode::getClass<RawTowerGeomContainer>(topNode,towergeomnode.c_str());
    if (!towergeom) {
      cerr << PHWHERE << " ERROR: Can't find " << towergeomnode << endl;
      exit(-1);
    }
  
    RawTowerContainer::ConstRange begin_end = towers->getTowers();
    RawTowerContainer::ConstIterator rtiter;
    for (rtiter = begin_end.first; rtiter !=  begin_end.second; ++rtiter) {
      RawTower *tower = rtiter->second;

      if (tower->get_energy() < _reco_e_threshold) continue;
      
      float towerid = tower->get_id();
      float ieta    = tower->get_bineta();
      float iphi    = tower->get_binphi();
      float eta     = towergeom->get_etacenter(tower->get_bineta());
      float phi     = towergeom->get_phicenter(tower->get_binphi());
      float e       = tower->get_energy();

      PHG4Particle* primary = towereval->max_truth_primary_by_energy(tower);

      float gparticleID = NAN;
      float gflavor     = NAN;
      float gnhits   = NAN;
      float gpx      = NAN;
      float gpy      = NAN;
      float gpz      = NAN;
      float ge       = NAN;

      float gpt = NAN;
      float geta = NAN;
      float gphi = NAN;

      float gvx      = NAN;
      float gvy      = NAN;
      float gvz      = NAN;

      float gembed   = NAN;
      float gedep    = NAN;
      float gmrad    = NAN;

      float efromtruth = NAN;

      if (primary) {

	gparticleID = primary->get_track_id();
	gflavor = primary->get_pid();

	std::set<PHG4Hit*> g4hits = trutheval->get_shower_from_primary(primary);
	gnhits = g4hits.size();
	gpx = primary->get_px();
	gpy = primary->get_py();
	gpz = primary->get_pz();
	ge = primary->get_e();

	gpt = sqrt(gpx * gpx + gpy * gpy);
	if (gpt != 0.0) geta = asinh(gpz / gpt);
	gphi = atan2(gpy, gpx);

	PHG4VtxPoint* vtx = trutheval->get_vertex(primary);

	if (vtx) {
	  gvx = vtx->get_x();
	  gvy = vtx->get_y();
	  gvz = vtx->get_z();
	}

	gembed = trutheval->get_embed(primary);
	gedep = trutheval->get_shower_energy_deposit(primary);
	gmrad = trutheval->get_shower_moliere_radius(primary);

	efromtruth = towereval->get_energy_contribution(tower, primary);
      }

      float tower_data[21] = {_ievent,
			      towerid,
			      ieta,
			      iphi,
			      eta,
			      phi,
			      e,
			      gparticleID,
			      gflavor,
			      gnhits,
			      geta,
			      gphi,
			      ge,
			      gpt,
			      gvx,
			      gvy,
			      gvz,
			      gembed,
			      gedep,
			      gmrad,
			      efromtruth
      };
      
      _ntp_tower->Fill(tower_data);
    }
  }

  //------------------------
  // fill the Cluster NTuple
  //------------------------

  if (_do_cluster_eval) {
    if (verbosity > 1) cout << "CaloEvaluator::filling gcluster ntuple..." << endl;

    string clusternode = "CLUSTER_" + _caloname;
    RawClusterContainer* clusters = findNode::getClass<RawClusterContainer>(topNode,clusternode.c_str());
    if (!clusters) {
      cerr << PHWHERE << " ERROR: Can't find " << clusternode << endl;
      exit(-1);
    }
  
    // for every cluster
    for (unsigned int icluster = 0; icluster < clusters->size(); icluster++) {
      RawCluster *cluster = clusters->getCluster(icluster);

      if (cluster->get_energy() < _reco_e_threshold) continue;
      
      float clusterID = cluster->get_id();
      float ntowers   = cluster->getNTowers();
      float eta       = cluster->get_eta();
      float phi       = cluster->get_phi();
      float e         = cluster->get_energy();
      
      PHG4Particle* primary = clustereval->max_truth_primary_by_energy(cluster);

      float gparticleID = NAN;
      float gflavor     = NAN;

      float gnhits   = NAN;
      float gpx      = NAN;
      float gpy      = NAN;
      float gpz      = NAN;
      float ge       = NAN;

      float gpt = NAN;
      float geta = NAN;
      float gphi = NAN;
      
      float gvx      = NAN;
      float gvy      = NAN;
      float gvz      = NAN;
      
      float gembed   = NAN;
      float gedep    = NAN;
      float gmrad    = NAN;

      float efromtruth = NAN;

      if (primary) {
	gparticleID = primary->get_track_id();
	gflavor = primary->get_pid();
	
	std::set<PHG4Hit*> g4hits = trutheval->get_shower_from_primary(primary);
	gnhits = g4hits.size();
	gpx = primary->get_px();
	gpy = primary->get_py();
	gpz = primary->get_pz();
	ge = primary->get_e();

	gpt = sqrt(gpx * gpx + gpy * gpy);
	if (gpt != 0.0) geta = asinh(gpz / gpt);
	gphi = atan2(gpy, gpx);

	PHG4VtxPoint* vtx = trutheval->get_vertex(primary);

	if (vtx) {
	  gvx = vtx->get_x();
	  gvy = vtx->get_y();
	  gvz = vtx->get_z();
	}
	
	gembed = trutheval->get_embed(primary);
	gedep = trutheval->get_shower_energy_deposit(primary);
	gmrad = trutheval->get_shower_moliere_radius(primary);

	efromtruth = clustereval->get_energy_contribution(cluster,
							  primary);
      }
      
      float cluster_data[20] = {_ievent,
				clusterID,
				ntowers,
				eta,
				phi,
				e,
				gparticleID,
				gflavor,
				gnhits,
				geta,
				gphi,
				ge,
				gpt,
				gvx,
				gvy,
				gvz,
				gembed,
				gedep,
				gmrad,
				efromtruth
      };

      _ntp_cluster->Fill(cluster_data);
    }
  }

  return;
}
int
QAG4SimulationCalorimeter::process_event_Cluster(PHCompositeNode *topNode)
{

  if (verbosity > 2)
    cout << "QAG4SimulationCalorimeter::process_event_Cluster() entered"
        << endl;

  Fun4AllHistoManager *hm = QAHistManagerDef::getHistoManager();
  assert(hm);
  string towergeomnodename = "TOWERGEOM_" + _calo_name;
  RawTowerGeomContainer *towergeom = findNode::getClass<RawTowerGeomContainer>(
      topNode, towergeomnodename.c_str());
  if (!towergeom)
    {
      cout << PHWHERE << ": Could not find node " << towergeomnodename.c_str()
          << endl;
      return Fun4AllReturnCodes::ABORTRUN;
    }

  //get a cluster count
  TH1D* h_norm = dynamic_cast<TH1D*>(hm->getHisto(
      get_histo_prefix() + "_Normalization"));
  assert(h_norm);

  std::string nodename = "CLUSTER_" + _calo_name;
  RawClusterContainer* clusters = findNode::getClass<RawClusterContainer>(
      topNode, nodename.c_str());
  assert(clusters);
  h_norm->Fill("Cluster", clusters->size());

  // get primary
  assert(_truth_container);
  assert(not _truth_container->GetMap().empty());
  PHG4Particle * last_primary = _truth_container->GetMap().rbegin()->second;
  assert(last_primary);

  if (verbosity > 2)
    {
      cout
          << "QAG4SimulationCalorimeter::process_event_Cluster() handle this truth particle"
          << endl;
      last_primary->identify();
    }

  assert(_caloevalstack);
  CaloRawClusterEval* clustereval = _caloevalstack->get_rawcluster_eval();
  assert(clustereval);

  TH1F* h = dynamic_cast<TH1F*>(hm->getHisto(
      get_histo_prefix() + "_Cluster_BestMatchERatio"));
  assert(h);

  RawCluster* cluster = clustereval->best_cluster_from(last_primary);
  if (cluster)
    {
      // has a cluster matched and best cluster selected

      if (verbosity > 3)
        cout << "QAG4SimulationCalorimeter::process_event_Cluster::"
            << _calo_name << " - get cluster with energy "
            << cluster->get_energy() << " VS primary energy "
            << last_primary->get_e() << endl;

      h->Fill(cluster->get_energy() / (last_primary->get_e() + 1e-9)); //avoids divide zero

      // now work on the projection:
      const CLHEP::Hep3Vector hit(cluster->get_position());

      const PHG4VtxPoint* primary_vtx = //
          _truth_container->GetPrimaryVtx(last_primary->get_vtx_id());
      assert(primary_vtx);
      if (verbosity > 2)
        {
          cout
              << "QAG4SimulationCalorimeter::process_event_Cluster() handle this vertex"
              << endl;
          primary_vtx->identify();
        }

      const CLHEP::Hep3Vector  vertex(primary_vtx->get_x(), primary_vtx->get_y(),
          primary_vtx->get_z());

      // projection axis
      CLHEP::Hep3Vector axis_proj(last_primary->get_px(), last_primary->get_py(),
          last_primary->get_pz());
      if (axis_proj.mag() == 0)
        axis_proj.set(0, 0, 1);
      axis_proj = axis_proj.unit();

      // azimuthal direction axis
      CLHEP::Hep3Vector axis_azimuth = axis_proj.cross(CLHEP::Hep3Vector(0, 0, 1));
      if (axis_azimuth.mag() == 0)
        axis_azimuth.set(1, 0, 0);
      axis_azimuth = axis_azimuth.unit();

      // polar direction axis
      CLHEP::Hep3Vector axis_polar = axis_proj.cross(axis_azimuth);
      assert(axis_polar.mag() > 0);
      axis_polar = axis_polar.unit();

      TH2F * hlat = dynamic_cast<TH2F*>(hm->getHisto(
          get_histo_prefix() + "_Cluster_LateralTruthProjection"));
      assert(hlat);

      const double hit_azimuth = axis_azimuth.dot(hit - vertex);
      const double hit_polar = axis_polar.dot(hit - vertex);
      hlat->Fill(hit_polar, hit_azimuth);

    }
  else
    {
      if (verbosity > 3)
        cout << "QAG4SimulationCalorimeter::process_event_Cluster::"
            << _calo_name << " - missing cluster !";
      h->Fill(0); // no cluster matched
    }

  return Fun4AllReturnCodes::EVENT_OK;
}