void JetEvaluator::fillOutputNtuples(PHCompositeNode *topNode) {
  
  if (Verbosity() > 2) cout << "JetEvaluator::fillOutputNtuples() entered" << endl;

  JetRecoEval*   recoeval = _jetevalstack->get_reco_eval();
  //JetTruthEval* trutheval = _jetevalstack->get_truth_eval();
 
  //-------------------------
  // fill the reco jet ntuple
  //-------------------------

  if (_do_recojet_eval) {
    if (Verbosity() > 1) cout << "JetEvaluator::filling recojet ntuple..." << endl;

    JetMap* recojets = findNode::getClass<JetMap>(topNode,_recojetname.c_str());
    if (!recojets) {
      cerr << PHWHERE << " ERROR: Can't find " << _recojetname << endl;
      exit(-1);
    }
  
    // for every recojet
    for (JetMap::Iter iter = recojets->begin();
	 iter != recojets->end();
	 ++iter) {
      Jet* recojet = iter->second;
      Jet* truthjet = recoeval->max_truth_jet_by_energy(recojet);

      float id    = recojet->get_id();
      float ncomp = recojet->size_comp();
      float eta   = recojet->get_eta();
      float phi   = recojet->get_phi();
      float e     = recojet->get_e();
      float pt    = recojet->get_pt();

      float gid        = NAN;
      float gncomp     = NAN;
      float geta       = NAN;
      float gphi       = NAN;
      float ge         = NAN;
      float gpt        = NAN;
      float efromtruth = NAN;

      if (truthjet) {
	gid    = truthjet->get_id();
	gncomp = truthjet->size_comp();
	geta   = truthjet->get_eta();
	gphi   = truthjet->get_phi();
	ge     = truthjet->get_e();
	gpt    = truthjet->get_pt();
	efromtruth = recoeval->get_energy_contribution(recojet,truthjet);
      }
      
      float recojet_data[14] = {(float) _ievent,
				id,
				ncomp,
				eta,
				phi,
				e,
				pt,
				gid,
				gncomp,
				geta,
				gphi,
				ge,
				gpt,
				efromtruth
      };

      _ntp_recojet->Fill(recojet_data);
    }
  }

  //-------------------------
  // fill the truth jet ntuple
  //-------------------------

  if (_do_truthjet_eval) {
    if (Verbosity() > 1) cout << "JetEvaluator::filling truthjet ntuple..." << endl;

    JetMap* truthjets = findNode::getClass<JetMap>(topNode,_truthjetname.c_str());
    if (!truthjets) {
      cerr << PHWHERE << " ERROR: Can't find " << _truthjetname << endl;
      exit(-1);
    }
  
    // for every truthjet
    for (JetMap::Iter iter = truthjets->begin();
	 iter != truthjets->end();
	 ++iter) {
      Jet* truthjet = iter->second;
      Jet* recojet = recoeval->best_jet_from(truthjet);

      float gid    = truthjet->get_id();
      float gncomp = truthjet->size_comp();
      float geta   = truthjet->get_eta();
      float gphi   = truthjet->get_phi();
      float ge     = truthjet->get_e();
      float gpt    = truthjet->get_pt();

      float id         = NAN;
      float ncomp      = NAN;
      float eta        = NAN;
      float phi        = NAN;
      float e          = NAN;
      float pt         = NAN;
      float efromtruth = NAN;

      if (recojet) {
	id         = recojet->get_id();
	ncomp      = recojet->size_comp();
	eta        = recojet->get_eta();
	phi        = recojet->get_phi();
	e          = recojet->get_e();
	pt         = recojet->get_pt();
	efromtruth = recoeval->get_energy_contribution(recojet,truthjet);
      }
      
      float truthjet_data[14] = {(float) _ievent,
				 gid,
				 gncomp,
				 geta,
				 gphi,
				 ge,
				 gpt,
				 id,
				 ncomp,
				 eta,
				 phi,
				 e,
				 pt,
				 efromtruth
      };

      _ntp_truthjet->Fill(truthjet_data);
    }
  }

  return;
}
int
LeptoquarksReco::process_event(PHCompositeNode *topNode)
{
  /* Reset branch map */
  ResetBranchMap();

  /* Create map to collect tau candidates.
   * Use energy as 'key' to the map because energy is unique for each jet, while there are sometimes multiple jets (same energy,
   * different jet ID) in the input jet collection. Also, map automatically sorts entries by key, i.e. this gives list of tau candidates
   * sorted by energy. */
  type_map_tcan tauCandidateMap;

  /* Get reco jets collection */
  JetMap* recojets = findNode::getClass<JetMap>(topNode,_jetcolname.c_str());
  if (!recojets)
    {
      cerr << PHWHERE << " ERROR: Can't find " << _jetcolname << endl;
      return Fun4AllReturnCodes::ABORTEVENT;
    }

  /* Get track collection with all tracks in this event */
  SvtxTrackMap* trackmap =
    findNode::getClass<SvtxTrackMap>(topNode,"SvtxTrackMap");
  if (!trackmap)
    {
      cout<< PHWHERE << "SvtxTrackMap node not found on node tree"
           << endl;
      return Fun4AllReturnCodes::ABORTEVENT;
    }

  /* Get vertex collection with all vertices in this event */
  SvtxVertexMap* vertexmap =
    findNode::getClass<SvtxVertexMap>(topNode,"SvtxVertexMap");
  if (!vertexmap)
    {
      cout<< PHWHERE << "SvtxVertexMap node not found on node tree"
          << endl;
      return Fun4AllReturnCodes::ABORTEVENT;
    }
    
  
    /* Get collection of truth particles from event generator */
  PHHepMCGenEventMap *genevtmap = findNode::getClass<PHHepMCGenEventMap>(topNode,"PHHepMCGenEventMap");
  if (!genevtmap) {
    cerr << PHWHERE << " ERROR: Can't find PHHepMCGenEventMap" << endl;
    return Fun4AllReturnCodes::ABORTEVENT;
  }

  /* create map of all tower collections and tower geometry collections used */
  type_map_cdata map_calotower;

  /* Select calorimeter to include */
  vector< RawTowerDefs::CalorimeterId > v_caloids;
  v_caloids.push_back( RawTowerDefs::CEMC );
  v_caloids.push_back( RawTowerDefs::HCALIN );
  v_caloids.push_back( RawTowerDefs::HCALOUT );
  v_caloids.push_back( RawTowerDefs::FEMC );
  v_caloids.push_back( RawTowerDefs::FHCAL );
  v_caloids.push_back( RawTowerDefs::EEMC );

  /* Fill map with calorimeter data */
  for ( unsigned i = 0; i < v_caloids.size(); i++ )
    {
      /* Get collection of towers */
      string towers_name = "TOWER_CALIB_";
      towers_name.append( RawTowerDefs::convert_caloid_to_name( v_caloids.at( i ) ) );

      RawTowerContainer *towers = findNode::getClass<RawTowerContainer>(topNode,towers_name);
      if (!towers) {
        cerr << PHWHERE << " ERROR: Can't find " << towers_name << endl;
        return Fun4AllReturnCodes::ABORTEVENT;
      }

      /* get geometry collection */
      string towergeom_name = "TOWERGEOM_";
      towergeom_name.append( RawTowerDefs::convert_caloid_to_name( v_caloids.at( i ) ) );

      RawTowerGeomContainer *geom = findNode::getClass<RawTowerGeomContainer>(topNode,towergeom_name);
      if (!geom) {
        cerr << PHWHERE << " ERROR: Can't find " << towergeom_name << endl;
        return Fun4AllReturnCodes::ABORTEVENT;
      }

      /* Insert tower and geometry collections in map */
      map_calotower.insert( make_pair( v_caloids.at( i ), make_pair( towers, geom ) ) );
    }


  /* Loop over all jets to collect tau candidate objects */
  for (JetMap::Iter iter = recojets->begin();
       iter != recojets->end();
       ++iter)
    {
      /* skip jets below energy threshold */
      if ( (iter->second)->get_e() < _tau_jet_emin )
        continue;

      /* create new tau candidate */
      PidCandidatev1 *tc = new PidCandidatev1();
      tc->set_candidate_id( (iter->second)->get_id() );
      tc->set_property( PidCandidate::jet_id , (iter->second)->get_id() );

      tc->set_property( PidCandidate::evtgen_pid, (int)0 );

      /* add tau candidate to collection */
      tauCandidateMap.insert( make_pair( (iter->second)->get_e(), tc ) );
    }
  
  /* vertex information */
  SvtxEvalStack *svtxevalstack = new SvtxEvalStack(topNode);
  
  /* Add jet information to tau candidates */
  AddJetInformation( tauCandidateMap, recojets, &map_calotower );

  /* Add jet structure information to tau candidates */
  AddJetStructureInformation( tauCandidateMap, &map_calotower );

  /* Add track information to tau candidates */
  AddTrackInformation( tauCandidateMap, trackmap, vertexmap, svtxevalstack, recojets->get_par());  

  /* Add tag for true Tau particle jet to tau candidates */
  AddTrueTauTag( tauCandidateMap, genevtmap );

  /* Add information about tau candidats to output tree */
  WritePidCandidatesToTree( tauCandidateMap );
  
  /* Add global event information to separate tree */
  AddGlobalEventInformation( tauCandidateMap, &map_calotower );

  /* fill event information tree */
  _t_event->Fill();

  /* count up event number */
  _ievent ++;

  return 0;
}