float
TrackProjectionTools::getE33Barrel( string detName, float phi, float eta ){

  string towernodename = "TOWER_CALIB_" + detName;
  // Grab the towers
  RawTowerContainer* towerList = findNode::getClass<RawTowerContainer>(_topNode, towernodename.c_str());
  if (!towerList)
    {
      std::cout << PHWHERE << ": Could not find node " << towernodename.c_str() << std::endl;
      return -1;
    }
  string towergeomnodename = "TOWERGEOM_" + detName;
  RawTowerGeomContainer *towergeo = findNode::getClass<RawTowerGeomContainer>(_topNode, towergeomnodename.c_str());
  if (! towergeo)
    {
      cout << PHWHERE << ": Could not find node " << towergeomnodename.c_str() << endl;
      return -1;
    }

  // calculate 3x3 and 5x5 tower energies
  int binphi = towergeo->get_phibin(phi);
  int bineta = towergeo->get_etabin(eta);

  float energy_3x3 = 0.0;
  float 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();
      }

    }
  }

  return energy_3x3;
}
Beispiel #2
0
pair<int, int>
Proto2ShowerCalib::find_max(RawTowerContainer* towers, int cluster_size)
{
  const int clus_edge_size = (cluster_size - 1) / 2;
  assert(clus_edge_size >= 0);

  pair<int, int> max(-1000, -1000);
  double max_e = 0;

  for (int col = 0; col < n_size; ++col)
    for (int row = 0; row < n_size; ++row)
      {
        double energy = 0;

        for (int dcol = col - clus_edge_size; dcol <= col + clus_edge_size;
            ++dcol)
          for (int drow = row - clus_edge_size; drow <= row + clus_edge_size;
              ++drow)
            {
              if (dcol < 0 or drow < 0)
                continue;

              RawTower * t = towers->getTower(dcol, drow);
              if (t)
                energy += t->get_energy();
            }

        if (energy > max_e)
          {
            max = make_pair(col, row);
            max_e = energy;
          }
      }

  return max;
}
Beispiel #3
0
int CaloTriggerSim::process_event(PHCompositeNode *topNode)
{
  if (verbosity > 0)
    std::cout << "CaloTriggerSim::process_event: entering" << std::endl;

  // pull out the tower containers and geometry objects at the start
  RawTowerContainer *towersEM3 = findNode::getClass<RawTowerContainer>(topNode, "TOWER_CALIB_CEMC");
  RawTowerContainer *towersIH3 = findNode::getClass<RawTowerContainer>(topNode, "TOWER_CALIB_HCALIN");
  RawTowerContainer *towersOH3 = findNode::getClass<RawTowerContainer>(topNode, "TOWER_CALIB_HCALOUT");
  if (verbosity > 0) {
    std::cout << "CaloTriggerSim::process_event: " << towersEM3->size() << " TOWER_CALIB_CEMC towers" << std::endl;
    std::cout << "CaloTriggerSim::process_event: " << towersIH3->size() << " TOWER_CALIB_HCALIN towers" << std::endl;
    std::cout << "CaloTriggerSim::process_event: " << towersOH3->size() << " TOWER_CALIB_HCALOUT towers" << std::endl;
  }

  RawTowerGeomContainer_Cylinderv1 *geomEM = findNode::getClass<RawTowerGeomContainer_Cylinderv1>(topNode, "TOWERGEOM_CEMC");
  RawTowerGeomContainer *geomIH = findNode::getClass<RawTowerGeomContainer>(topNode, "TOWERGEOM_HCALIN");
  RawTowerGeomContainer *geomOH = findNode::getClass<RawTowerGeomContainer>(topNode, "TOWERGEOM_HCALOUT");

  // get the binning from the geometry (different for 1D vs 2D...)
  int geom_etabins = geomEM->get_etabins();
  int geom_phibins = geomEM->get_phibins();

  // if internal knowledge of geometry is unset, set it now (should
  // only happen once, on the first event)
  if (_EMCAL_1x1_NETA < 0)
  {
    _EMCAL_1x1_NETA = geom_etabins;
    _EMCAL_1x1_NPHI = geom_phibins;

    // half as many 2x2 windows along each axis as 1x1
    _EMCAL_2x2_NETA = geom_etabins / 2;
    _EMCAL_2x2_NPHI = geom_phibins / 2;

    // each 2x2 window defines a 4x4 window for which that 2x2 window
    // is the upper-left corner, so there are as many 4x4's as 2x2's
    // (except in eta, where the edge effect means there is 1 fewer)
    _EMCAL_4x4_NETA = geom_etabins / 2 - 1;
    _EMCAL_4x4_NPHI = geom_phibins / 2;

    // reset all maps
    _EMCAL_1x1_MAP.resize(_EMCAL_1x1_NETA, std::vector<float>(_EMCAL_1x1_NPHI, 0));
    _EMCAL_2x2_MAP.resize(_EMCAL_2x2_NETA, std::vector<float>(_EMCAL_2x2_NPHI, 0));
    _EMCAL_4x4_MAP.resize(_EMCAL_4x4_NETA, std::vector<float>(_EMCAL_4x4_NPHI, 0));

    if (verbosity > 0)
    {
      std::cout << "CaloTriggerSim::process_event: setting number of window in eta / phi,";
      std::cout << "1x1 are " << _EMCAL_1x1_NETA << " / " << _EMCAL_1x1_NPHI << ", ";
      std::cout << "2x2 are " << _EMCAL_2x2_NETA << " / " << _EMCAL_2x2_NPHI << ", ";
      std::cout << "4x4 are " << _EMCAL_4x4_NETA << " / " << _EMCAL_4x4_NPHI << std::endl;
    }
  }

  // reset 1x1 map
  for (int ieta = 0; ieta < _EMCAL_1x1_NETA; ieta++)
  {
    for (int iphi = 0; iphi < _EMCAL_1x1_NPHI; iphi++)
    {
      _EMCAL_1x1_MAP[ieta][iphi] = 0;
    }
  }

  // iterate over EMCal towers, constructing 1x1's
  RawTowerContainer::ConstRange begin_end = towersEM3->getTowers();
  for (RawTowerContainer::ConstIterator rtiter = begin_end.first; rtiter != begin_end.second; ++rtiter)
  {
    RawTower *tower = rtiter->second;
    RawTowerGeom *tower_geom = geomEM->get_tower_geometry(tower->get_key());

    float this_eta = tower_geom->get_eta();
    float this_phi = tower_geom->get_phi();
    int this_etabin = geomEM->get_etabin(this_eta);
    int this_phibin = geomEM->get_phibin(this_phi);
    float this_E = tower->get_energy();

    _EMCAL_1x1_MAP[this_etabin][this_phibin] += this_E;

    if (verbosity > 1 && tower->get_energy() > 1)
    {
      std::cout << "CaloTriggerSim::process_event: EMCal 1x1 tower eta ( bin ) / phi ( bin ) / E = " << std::setprecision(6) << this_eta << " ( " << this_etabin << " ) / " << this_phi << " ( " << this_phibin << " ) / " << this_E << std::endl;
    }
  }

  // reset 2x2 map and best
  for (int ieta = 0; ieta < _EMCAL_2x2_NETA; ieta++)
  {
    for (int iphi = 0; iphi < _EMCAL_2x2_NPHI; iphi++)
    {
      _EMCAL_2x2_MAP[ieta][iphi] = 0;
    }
  }

  _EMCAL_2x2_BEST_E = 0;
  _EMCAL_2x2_BEST_PHI = 0;
  _EMCAL_2x2_BEST_ETA = 0;

  // now reconstruct 2x2 map from 1x1 map
  for (int ieta = 0; ieta < _EMCAL_2x2_NETA; ieta++)
  {
    for (int iphi = 0; iphi < _EMCAL_2x2_NPHI; iphi++)
    {
      float this_sum = 0;

      this_sum += _EMCAL_1x1_MAP[2 * ieta][2 * iphi];
      this_sum += _EMCAL_1x1_MAP[2 * ieta][2 * iphi + 1];  // 2 * iphi + 1 is safe, since _EMCAL_2x2_NPHI = _EMCAL_1x1_NPHI / 2
      this_sum += _EMCAL_1x1_MAP[2 * ieta + 1][2 * iphi];  // 2 * ieta + 1 is safe, since _EMCAL_2x2_NETA = _EMCAL_1x1_NETA / 2
      this_sum += _EMCAL_1x1_MAP[2 * ieta + 1][2 * iphi + 1];

      if (_emulate_truncation) {
	this_sum = truncate_8bit( this_sum );
      }

      // populate 2x2 map
      _EMCAL_2x2_MAP[ieta][iphi] = this_sum;

      // to calculate the eta, phi position, take the average of that of the 1x1's
      float this_eta = 0.5 * (geomEM->get_etacenter(2 * ieta) + geomEM->get_etacenter(2 * ieta + 1));
      float this_phi = 0.5 * (geomEM->get_phicenter(2 * iphi) + geomEM->get_phicenter(2 * iphi + 1));
      // wrap-around phi (apparently needed for 2D geometry?)
      if (this_phi > 3.14159) this_phi -= 2 * 3.14159;
      if (this_phi < -3.14159) this_phi += 2 * 3.14159;

      if (verbosity > 1 && this_sum > 1)
      {
        std::cout << "CaloTriggerSim::process_event: EMCal 2x2 tower eta ( bin ) / phi ( bin ) / E = " << std::setprecision(6) << this_eta << " ( " << ieta << " ) / " << this_phi << " ( " << iphi << " ) / " << this_sum << std::endl;
      }

      if (this_sum > _EMCAL_2x2_BEST_E)
      {
        _EMCAL_2x2_BEST_E = this_sum;
        _EMCAL_2x2_BEST_PHI = this_phi;
        _EMCAL_2x2_BEST_ETA = this_eta;
      }
    }
  }

  if (verbosity > 0)
  {
    std::cout << "CaloTriggerSim::process_event: best EMCal 2x2 window is at eta / phi = " << _EMCAL_2x2_BEST_ETA << " / " << _EMCAL_2x2_BEST_PHI << " and E = " << _EMCAL_2x2_BEST_E << std::endl;
  }

  // reset 4x4 map & best
  for (int ieta = 0; ieta < _EMCAL_4x4_NETA; ieta++)
  {
    for (int iphi = 0; iphi < _EMCAL_4x4_NPHI; iphi++)
    {
      _EMCAL_4x4_MAP[ieta][iphi] = 0;
    }
  }

  _EMCAL_4x4_BEST_E = 0;
  _EMCAL_4x4_BEST_PHI = 0;
  _EMCAL_4x4_BEST_ETA = 0;

  int emcal_4x4_best_iphi = -1;
  int emcal_4x4_best_ieta = -1;

  // now reconstruct (sliding) 4x4 map from 2x2 map
  for (int ieta = 0; ieta < _EMCAL_4x4_NETA; ieta++)
  {
    for (int iphi = 0; iphi < _EMCAL_4x4_NPHI; iphi++)
    {
      // for eta calculation (since eta distribution is potentially
      // non-uniform), average positions of all four towers
      float this_eta = 0.25 * (geomEM->get_etacenter(2 * ieta) + geomEM->get_etacenter(2 * ieta + 1) + geomEM->get_etacenter(2 * ieta + 2) + geomEM->get_etacenter(2 * ieta + 3));
      // for phi calculation (since phi distribution is uniform), take
      // first tower and add 1.5 tower widths
      float this_phi = geomEM->get_phicenter(2 * iphi) + 1.5 * (geomEM->get_phicenter(2 * iphi + 1) - geomEM->get_phicenter(2 * iphi));
      // wrap-around phi (apparently needed for 2D geometry?)
      if (this_phi > 3.14159) this_phi -= 2 * 3.14159;
      if (this_phi < -3.14159) this_phi += 2 * 3.14159;

      float this_sum = 0;

      this_sum += _EMCAL_2x2_MAP[ieta][iphi];
      this_sum += _EMCAL_2x2_MAP[ieta + 1][iphi];  // ieta + 1 is safe, since _EMCAL_4x4_NETA = _EMCAL_2x2_NETA - 1

      if (iphi != _EMCAL_4x4_NPHI - 1)
      {
        // if we are not in the last phi row, can safely access 'iphi+1'
        this_sum += _EMCAL_2x2_MAP[ieta][iphi + 1];
        this_sum += _EMCAL_2x2_MAP[ieta + 1][iphi + 1];
      }
      else
      {
        // if we are in the last phi row, wrap back around to zero
        this_sum += _EMCAL_2x2_MAP[ieta][0];
        this_sum += _EMCAL_2x2_MAP[ieta + 1][0];
      }

      _EMCAL_4x4_MAP[ieta][iphi] = this_sum;

      if (verbosity > 1 && this_sum > 1)
      {
        std::cout << "CaloTriggerSim::process_event: EMCal 4x4 tower eta ( bin ) / phi ( bin ) / E = " << std::setprecision(6) << this_eta << " ( " << ieta << " ) / " << this_phi << " ( " << iphi << " ) / " << this_sum << std::endl;
      }

      if (this_sum > _EMCAL_4x4_BEST_E) {
	
	_EMCAL_4x4_BEST_E = this_sum;
	_EMCAL_4x4_BEST_PHI = this_phi;
	_EMCAL_4x4_BEST_ETA = this_eta;
	
	emcal_4x4_best_iphi = iphi;
	emcal_4x4_best_ieta = ieta;
  
      }
    }
  }


  _EMCAL_4x4_BEST2_E = 0;
  _EMCAL_4x4_BEST2_PHI = 0;
  _EMCAL_4x4_BEST2_ETA = 0;

  // find second-largest 4x4 which is > 1 tower away...
  for (int ieta = 0; ieta < _EMCAL_4x4_NETA; ieta++)
  {
    for (int iphi = 0; iphi < _EMCAL_4x4_NPHI; iphi++)
    {

      int deta = ieta - emcal_4x4_best_ieta;
      int dphi = ( iphi - emcal_4x4_best_iphi ) % _EMCAL_4x4_NPHI ;

      if ( abs( deta ) < 1.5 && abs( dphi ) < 1.5 ) 
	continue;

      float this_eta = 0.25 * (geomEM->get_etacenter(2 * ieta) + geomEM->get_etacenter(2 * ieta + 1) + geomEM->get_etacenter(2 * ieta + 2) + geomEM->get_etacenter(2 * ieta + 3));
      float this_phi = geomEM->get_phicenter(2 * iphi) + 1.5 * (geomEM->get_phicenter(2 * iphi + 1) - geomEM->get_phicenter(2 * iphi));

      if (this_phi > 3.14159) this_phi -= 2 * 3.14159;
      if (this_phi < -3.14159) this_phi += 2 * 3.14159;

      float this_sum = _EMCAL_4x4_MAP[ieta][iphi];
      
      if (this_sum > _EMCAL_4x4_BEST2_E) {
	
	_EMCAL_4x4_BEST2_E = this_sum;
	_EMCAL_4x4_BEST2_PHI = this_phi;
	_EMCAL_4x4_BEST2_ETA = this_eta;

      }

    }
  }

  if (verbosity > 0)
  {
    std::cout << "CaloTriggerSim::process_event: best EMCal 4x4 window is at eta / phi = " << _EMCAL_4x4_BEST_ETA << " / " << _EMCAL_4x4_BEST_PHI << " and E = " << _EMCAL_4x4_BEST_E << std::endl;
    std::cout << "CaloTriggerSim::process_event: 2nd best EMCal 4x4 window is at eta / phi = " << _EMCAL_4x4_BEST2_ETA << " / " << _EMCAL_4x4_BEST2_PHI << " and E = " << _EMCAL_4x4_BEST2_E << std::endl;
  }

  // begin full calo sim

  // get the 0.1x0.1 binning from the OHCal geometry
  int geomOH_etabins = geomOH->get_etabins();
  int geomOH_phibins = geomOH->get_phibins();

  // if internal knowledge of geometry is unset, set it now
  if (_FULLCALO_0p1x0p1_NETA < 0)
  {
    _FULLCALO_PHI_START = geomOH->get_phibounds( 0 ).first;
    _FULLCALO_PHI_END = geomOH->get_phibounds( geomOH_phibins - 1 ).second;

    _FULLCALO_0p1x0p1_NETA = geomOH_etabins;
    _FULLCALO_0p1x0p1_NPHI = geomOH_phibins;

    // half as many 0.2x0.2 windows along each axis as 0.1x0.1
    _FULLCALO_0p2x0p2_NETA = geomOH_etabins / 2;
    _FULLCALO_0p2x0p2_NPHI = geomOH_phibins / 2;

    // each 0.2x0.2 window defines a 0.4x0.4 window for which that
    // 0.2x0.2 window is the upper-left corner, so there are as many
    // 0.4x0.4's as 0.2x0.2's (except in eta, where the edge effect
    // means there is 1 fewer)
    _FULLCALO_0p4x0p4_NETA = geomOH_etabins / 2 - 1;
    _FULLCALO_0p4x0p4_NPHI = geomOH_phibins / 2;

    // for 0.6x0.6 windows, the above logic applies, except that the
    // edge effect causes there to be 2 fewer less in eta
    _FULLCALO_0p6x0p6_NETA = geomOH_etabins / 2 - 2;
    _FULLCALO_0p6x0p6_NPHI = geomOH_phibins / 2;

    // for 0.8x0.8 windows, the above logic applies, except that the
    // edge effect causes there to be 3 fewer less in eta
    _FULLCALO_0p8x0p8_NETA = geomOH_etabins / 2 - 3;
    _FULLCALO_0p8x0p8_NPHI = geomOH_phibins / 2;

    // for 1.0x1.0 windows, the above logic applies, except that the
    // edge effect causes there to be 4 fewer less in eta
    _FULLCALO_1p0x1p0_NETA = geomOH_etabins / 2 - 4;
    _FULLCALO_1p0x1p0_NPHI = geomOH_phibins / 2;

    // reset all maps
    _FULLCALO_0p1x0p1_MAP.resize(_FULLCALO_0p1x0p1_NETA, std::vector<float>(_FULLCALO_0p1x0p1_NPHI, 0));
    _FULLCALO_0p2x0p2_MAP.resize(_FULLCALO_0p2x0p2_NETA, std::vector<float>(_FULLCALO_0p2x0p2_NPHI, 0));
    _FULLCALO_0p4x0p4_MAP.resize(_FULLCALO_0p4x0p4_NETA, std::vector<float>(_FULLCALO_0p4x0p4_NPHI, 0));
    _FULLCALO_0p6x0p6_MAP.resize(_FULLCALO_0p6x0p6_NETA, std::vector<float>(_FULLCALO_0p6x0p6_NPHI, 0));
    _FULLCALO_0p8x0p8_MAP.resize(_FULLCALO_0p8x0p8_NETA, std::vector<float>(_FULLCALO_0p8x0p8_NPHI, 0));
    _FULLCALO_1p0x1p0_MAP.resize(_FULLCALO_1p0x1p0_NETA, std::vector<float>(_FULLCALO_1p0x1p0_NPHI, 0));

    if (verbosity > 0)
    {
      std::cout << "CaloTriggerSim::process_event: determining phi range for 0.1x0.1 full calo map: " << _FULLCALO_PHI_START << " to " << _FULLCALO_PHI_END << std::endl;
      std::cout << "CaloTriggerSim::process_event: setting number of full calo window in eta / phi:" << std::endl;
      std::cout << "  0.1x0.1 are " << _FULLCALO_0p1x0p1_NETA << " / " << _FULLCALO_0p1x0p1_NPHI << ", ";
      std::cout << "0.2x0.2 are " << _FULLCALO_0p2x0p2_NETA << " / " << _FULLCALO_0p2x0p2_NPHI << ", ";
      std::cout << "0.4x0.4 are " << _FULLCALO_0p4x0p4_NETA << " / " << _FULLCALO_0p4x0p4_NPHI << ", ";
      std::cout << "0.6x0.6 are " << _FULLCALO_0p6x0p6_NETA << " / " << _FULLCALO_0p6x0p6_NPHI << ", ";
      std::cout << "0.8x0.8 are " << _FULLCALO_0p8x0p8_NETA << " / " << _FULLCALO_0p8x0p8_NPHI << ", ";
      std::cout << "1.0x1.0 are " << _FULLCALO_1p0x1p0_NETA << " / " << _FULLCALO_1p0x1p0_NPHI << std::endl;
    }
  }

  // reset 0.1x0.1 map
  for (int ieta = 0; ieta < _FULLCALO_0p1x0p1_NETA; ieta++)
  {
    for (int iphi = 0; iphi < _FULLCALO_0p1x0p1_NPHI; iphi++)
    {
      _FULLCALO_0p1x0p1_MAP[ieta][iphi] = 0;
    }
  }

  // iterate over EMCal towers, filling in the 0.1x0.1 region they contribute to
  RawTowerContainer::ConstRange begin_end_EM = towersEM3->getTowers();
  for (RawTowerContainer::ConstIterator rtiter = begin_end_EM.first; rtiter != begin_end_EM.second; ++rtiter)
  {
    RawTower *tower = rtiter->second;
    RawTowerGeom *tower_geom = geomEM->get_tower_geometry(tower->get_key());

    float this_eta = tower_geom->get_eta();
    float this_phi = tower_geom->get_phi();
    if (this_phi < _FULLCALO_PHI_START) this_phi += 2*3.14159;
    if (this_phi > _FULLCALO_PHI_END) this_phi -= 2*3.14159;
 
    // note: look up eta/phi index based on OHCal geometry, since this
    // defines the 0.1x0.1 regions
    int this_etabin = geomOH->get_etabin( this_eta );
    int this_phibin = geomOH->get_phibin( this_phi );
    float this_E = tower->get_energy();

    _FULLCALO_0p1x0p1_MAP[ this_etabin ][ this_phibin ] += this_E;

    if (verbosity > 1 && tower->get_energy() > 1)
    {
      std::cout << "CaloTriggerSim::process_event: EMCal tower at eta / phi (added to fullcalo map with etabin / phibin ) / E = " << std::setprecision(6) << this_eta << " / " << this_phi << " ( " << this_etabin << " / " << this_phibin << " ) / " << this_E << std::endl;
    }
  }

  // iterate over IHCal towers, filling in the 0.1x0.1 region they contribute to
  RawTowerContainer::ConstRange begin_end_IH = towersIH3->getTowers();
  for (RawTowerContainer::ConstIterator rtiter = begin_end_IH.first; rtiter != begin_end_IH.second; ++rtiter)
  {
    RawTower *tower = rtiter->second;
    RawTowerGeom *tower_geom = geomIH->get_tower_geometry(tower->get_key());

    float this_eta = tower_geom->get_eta();
    float this_phi = tower_geom->get_phi();
    if (this_phi < _FULLCALO_PHI_START) this_phi += 2*3.14159;
    if (this_phi > _FULLCALO_PHI_END) this_phi -= 2*3.14159;
 
    // note: look up eta/phi index based on OHCal geometry, even though I
    // think it is by construction the same as the IHCal geometry...
    int this_etabin = geomOH->get_etabin( this_eta );
    int this_phibin = geomOH->get_phibin( this_phi );
    float this_E = tower->get_energy();

    _FULLCALO_0p1x0p1_MAP[ this_etabin ][ this_phibin ] += this_E;

    if (verbosity > 1 && tower->get_energy() > 0.5)
    {
      std::cout << "CaloTriggerSim::process_event: IHCal tower at eta / phi (added to fullcalo map with etabin / phibin ) / E = " << std::setprecision(6) << this_eta << " / " << this_phi << " ( " << this_etabin << " / " << this_phibin << " ) / " << this_E << std::endl;
    }
  }

  // iterate over OHCal towers, filling in the 0.1x0.1 region they contribute to
  RawTowerContainer::ConstRange begin_end_OH = towersOH3->getTowers();
  for (RawTowerContainer::ConstIterator rtiter = begin_end_OH.first; rtiter != begin_end_OH.second; ++rtiter)
  {
    RawTower *tower = rtiter->second;
    RawTowerGeom *tower_geom = geomOH->get_tower_geometry(tower->get_key());

    float this_eta = tower_geom->get_eta();
    float this_phi = tower_geom->get_phi();
    if (this_phi < _FULLCALO_PHI_START) this_phi += 2*3.14159;
    if (this_phi > _FULLCALO_PHI_END) this_phi -= 2*3.14159;
 
    // note: use the nominal eta/phi index, since the fullcalo 0.1x0.1
    // map is defined by the OHCal geometry itself
    int this_etabin = geomOH->get_etabin( this_eta );
    int this_phibin = geomOH->get_phibin( this_phi );
    float this_E = tower->get_energy();

    _FULLCALO_0p1x0p1_MAP[ this_etabin ][ this_phibin ] += this_E;

    if (verbosity > 1 && tower->get_energy() > 0.5)
    {
      std::cout << "CaloTriggerSim::process_event: OHCal tower at eta / phi (added to fullcalo map with etabin / phibin ) / E = " << std::setprecision(6) << this_eta << " / " << this_phi << " ( " << this_etabin << " / " << this_phibin << " ) / " << this_E << std::endl;
    }
  }

  // reset 0.2x0.2 map and best
  for (int ieta = 0; ieta < _FULLCALO_0p2x0p2_NETA; ieta++)
  {
    for (int iphi = 0; iphi < _FULLCALO_0p2x0p2_NPHI; iphi++)
    {
      _FULLCALO_0p2x0p2_MAP[ ieta ][ iphi ] = 0;
    }
  }

  _FULLCALO_0p2x0p2_BEST_E = 0;
  _FULLCALO_0p2x0p2_BEST_PHI = 0;
  _FULLCALO_0p2x0p2_BEST_ETA = 0;

  // now reconstruct (non-sliding) 0.2x0.2 map from 0.1x0.1 map
  for (int ieta = 0; ieta < _FULLCALO_0p2x0p2_NETA; ieta++)
  {
    for (int iphi = 0; iphi < _FULLCALO_0p2x0p2_NPHI; iphi++)
    {
      float this_sum = 0;

      this_sum += _FULLCALO_0p1x0p1_MAP[2 * ieta][2 * iphi];
      this_sum += _FULLCALO_0p1x0p1_MAP[2 * ieta][2 * iphi + 1];  // 2 * iphi + 1 is safe, since _FULLCALO_0p2x0p2_NPHI = _FULLCALO_0p1x0p1_NPHI / 2
      this_sum += _FULLCALO_0p1x0p1_MAP[2 * ieta + 1][2 * iphi];  // 2 * ieta + 1 is safe, since _FULLCALO_0p2x0p2_NETA = _FULLCALO_0p1x0p1_NETA / 2
      this_sum += _FULLCALO_0p1x0p1_MAP[2 * ieta + 1][2 * iphi + 1];

      // populate 0.2x0.2 map
      _FULLCALO_0p2x0p2_MAP[ieta][iphi] = this_sum;

      // to calculate the eta, phi position, take the average of that
      // of the contributing 0.1x0.1's (which are defined by the OHCal geometry)
      float this_eta = 0.5 * (geomOH->get_etacenter(2 * ieta) + geomOH->get_etacenter(2 * ieta + 1));
      float this_phi = 0.5 * (geomOH->get_phicenter(2 * iphi) + geomOH->get_phicenter(2 * iphi + 1));

      if (verbosity > 1 && this_sum > 1)
      {
        std::cout << "CaloTriggerSim::process_event: FullCalo 0.2x0.2 window eta ( bin ) / phi ( bin ) / E = " << std::setprecision(6) << this_eta << " ( " << ieta << " ) / " << this_phi << " ( " << iphi << " ) / " << this_sum << std::endl;
      }

      if (this_sum > _FULLCALO_0p2x0p2_BEST_E)
      {
        _FULLCALO_0p2x0p2_BEST_E = this_sum;
        _FULLCALO_0p2x0p2_BEST_PHI = this_phi;
        _FULLCALO_0p2x0p2_BEST_ETA = this_eta;
      }
    }
  }

  if (verbosity > 0)
  {
    std::cout << "CaloTriggerSim::process_event: best FullCalo 0.2x0.2 window is at eta / phi = " << _FULLCALO_0p2x0p2_BEST_ETA << " / " << _FULLCALO_0p2x0p2_BEST_PHI << " and E = " << _FULLCALO_0p2x0p2_BEST_E << std::endl;
  }

  // reset fullcalo 0.4x0.4 map & best
  for (int ieta = 0; ieta < _FULLCALO_0p4x0p4_NETA; ieta++)
  {
    for (int iphi = 0; iphi < _FULLCALO_0p4x0p4_NPHI; iphi++)
    {
      _FULLCALO_0p4x0p4_MAP[ ieta ][ iphi ] = 0;
    }
  }

  _FULLCALO_0p4x0p4_BEST_E = 0;
  _FULLCALO_0p4x0p4_BEST_PHI = 0;
  _FULLCALO_0p4x0p4_BEST_ETA = 0;

  // now reconstruct (sliding) 0.4x0.4 map from 0.2x0.2 map
  for (int ieta = 0; ieta < _FULLCALO_0p4x0p4_NETA; ieta++)
  {
    for (int iphi = 0; iphi < _FULLCALO_0p4x0p4_NPHI; iphi++)
    {
      // for eta calculation, use position of corner tower and add 1.5
      // tower widths
      float this_eta = geomOH->get_etacenter(2 * ieta) + 1.5 * ( geomOH->get_etacenter( 1 ) - geomOH->get_etacenter( 0 ) );
      // for phi calculation, use position of corner tower and add 1.5
      // tower widths
      float this_phi = geomOH->get_phicenter(2 * iphi) + 1.5 * (geomOH->get_phicenter( 1 ) - geomOH->get_phicenter( 0 ) );

      float this_sum = 0;

      this_sum += _FULLCALO_0p2x0p2_MAP[ieta][iphi];
      this_sum += _FULLCALO_0p2x0p2_MAP[ieta + 1][iphi];  // 2 * ieta + 1 is safe, since _FULLCALO_0p4x0p4_NETA = _FULLCALO_0p4x0p4_NETA - 1

      // add 1 to phi, but take modulus w.r.t. _FULLCALO_0p2x0p2_NPHI
      // in case we have wrapped back around
      this_sum += _FULLCALO_0p2x0p2_MAP[ieta][ ( iphi + 1 ) % _FULLCALO_0p2x0p2_NPHI ];
      this_sum += _FULLCALO_0p2x0p2_MAP[ieta + 1][ ( iphi + 1 ) % _FULLCALO_0p2x0p2_NPHI ];

      _FULLCALO_0p4x0p4_MAP[ieta][iphi] = this_sum;

      if (verbosity > 1 && this_sum > 2)
      {
        std::cout << "CaloTriggerSim::process_event: FullCalo  0.4x0.4 tower eta ( bin ) / phi ( bin ) / E = " << std::setprecision(6) << this_eta << " ( " << ieta << " ) / " << this_phi << " ( " << iphi << " ) / " << this_sum << std::endl;
      }

      if (this_sum > _FULLCALO_0p4x0p4_BEST_E)
      {
        _FULLCALO_0p4x0p4_BEST_E = this_sum;
        _FULLCALO_0p4x0p4_BEST_PHI = this_phi;
        _FULLCALO_0p4x0p4_BEST_ETA = this_eta;
      }
    }
  }

  if (verbosity > 0)
  {
    std::cout << "CaloTriggerSim::process_event: best FullCalo 0.4x0.4 window is at eta / phi = " << _FULLCALO_0p4x0p4_BEST_ETA << " / " << _FULLCALO_0p4x0p4_BEST_PHI << " and E = " << _FULLCALO_0p4x0p4_BEST_E << std::endl;
  }

  // reset fullcalo 0.6x0.6 map & best
  for (int ieta = 0; ieta < _FULLCALO_0p6x0p6_NETA; ieta++)
  {
    for (int iphi = 0; iphi < _FULLCALO_0p6x0p6_NPHI; iphi++)
    {
      _FULLCALO_0p6x0p6_MAP[ ieta ][ iphi ] = 0;
    }
  }

  _FULLCALO_0p6x0p6_BEST_E = 0;
  _FULLCALO_0p6x0p6_BEST_PHI = 0;
  _FULLCALO_0p6x0p6_BEST_ETA = 0;

  // now reconstruct (sliding) 0.6x0.6 map from 0.2x0.2 map
  for (int ieta = 0; ieta < _FULLCALO_0p6x0p6_NETA; ieta++)
  {
    for (int iphi = 0; iphi < _FULLCALO_0p6x0p6_NPHI; iphi++)
    {
      // for eta calculation, use position of corner tower and add 2.5
      // tower widths
      float this_eta = geomOH->get_etacenter(2 * ieta) + 2.5 * ( geomOH->get_etacenter( 1 ) - geomOH->get_etacenter( 0 ) );
      // for phi calculation, use position of corner tower and add 2.5
      // tower widths
      float this_phi = geomOH->get_phicenter(2 * iphi) + 2.5 * (geomOH->get_phicenter( 1 ) - geomOH->get_phicenter( 0 ) );

      float this_sum = 0;

      this_sum += _FULLCALO_0p2x0p2_MAP[ieta][iphi];
      this_sum += _FULLCALO_0p2x0p2_MAP[ieta + 1][iphi];  // ieta + 1 is safe, since _FULLCALO_0p6x0p6_NETA = _FULLCALO_0p2x0p2_NETA - 2
      this_sum += _FULLCALO_0p2x0p2_MAP[ieta + 2][iphi];  // ieta + 2 is safe, since _FULLCALO_0p6x0p6_NETA = _FULLCALO_0p2x0p2_NETA - 2

      // add 1 to phi, but take modulus w.r.t. _FULLCALO_0p2x0p2_NPHI
      // in case we have wrapped back around
      this_sum += _FULLCALO_0p2x0p2_MAP[ieta][ ( iphi + 1 ) % _FULLCALO_0p2x0p2_NPHI ];
      this_sum += _FULLCALO_0p2x0p2_MAP[ieta + 1][ ( iphi + 1 ) % _FULLCALO_0p2x0p2_NPHI ];
      this_sum += _FULLCALO_0p2x0p2_MAP[ieta + 2][ ( iphi + 1 ) % _FULLCALO_0p2x0p2_NPHI ];
      // add 2 to phi, but take modulus w.r.t. _FULLCALO_0p2x0p2_NPHI
      // in case we have wrapped back around
      this_sum += _FULLCALO_0p2x0p2_MAP[ieta][ ( iphi + 2 ) % _FULLCALO_0p2x0p2_NPHI ];
      this_sum += _FULLCALO_0p2x0p2_MAP[ieta + 1][ ( iphi + 2 ) % _FULLCALO_0p2x0p2_NPHI ];
      this_sum += _FULLCALO_0p2x0p2_MAP[ieta + 2][ ( iphi + 2 ) % _FULLCALO_0p2x0p2_NPHI ];

      _FULLCALO_0p6x0p6_MAP[ieta][iphi] = this_sum;

      if (verbosity > 1 && this_sum > 3)
      {
        std::cout << "CaloTriggerSim::process_event: FullCalo  0.6x0.6 tower eta ( bin ) / phi ( bin ) / E = " << std::setprecision(6) << this_eta << " ( " << ieta << " ) / " << this_phi << " ( " << iphi << " ) / " << this_sum << std::endl;
      }

      if (this_sum > _FULLCALO_0p6x0p6_BEST_E)
      {
        _FULLCALO_0p6x0p6_BEST_E = this_sum;
        _FULLCALO_0p6x0p6_BEST_PHI = this_phi;
        _FULLCALO_0p6x0p6_BEST_ETA = this_eta;
      }
    }
  }

  if (verbosity > 0)
  {
    std::cout << "CaloTriggerSim::process_event: best FullCalo 0.6x0.6 window is at eta / phi = " << _FULLCALO_0p6x0p6_BEST_ETA << " / " << _FULLCALO_0p6x0p6_BEST_PHI << " and E = " << _FULLCALO_0p6x0p6_BEST_E << std::endl;
  }

  // reset fullcalo 0.8x0.8 map & best
  for (int ieta = 0; ieta < _FULLCALO_0p8x0p8_NETA; ieta++)
  {
    for (int iphi = 0; iphi < _FULLCALO_0p8x0p8_NPHI; iphi++)
    {
      _FULLCALO_0p8x0p8_MAP[ ieta ][ iphi ] = 0;
    }
  }

  _FULLCALO_0p8x0p8_BEST_E = 0;
  _FULLCALO_0p8x0p8_BEST_PHI = 0;
  _FULLCALO_0p8x0p8_BEST_ETA = 0;

  // now reconstruct (sliding) 0.8x0.8 map from 0.2x0.2 map
  for (int ieta = 0; ieta < _FULLCALO_0p8x0p8_NETA; ieta++)
  {
    for (int iphi = 0; iphi < _FULLCALO_0p8x0p8_NPHI; iphi++)
    {
      // for eta calculation, use position of corner tower and add 3.5
      // tower widths
      float this_eta = geomOH->get_etacenter(2 * ieta) + 3.5 * ( geomOH->get_etacenter( 1 ) - geomOH->get_etacenter( 0 ) );
      // for phi calculation, use position of corner tower and add 3.5
      // tower widths
      float this_phi = geomOH->get_phicenter(2 * iphi) + 3.5 * (geomOH->get_phicenter( 1 ) - geomOH->get_phicenter( 0 ) );

      float this_sum = 0;

      this_sum += _FULLCALO_0p2x0p2_MAP[ieta][iphi];
      this_sum += _FULLCALO_0p2x0p2_MAP[ieta + 1][iphi];  // ieta + 1 is safe, since _FULLCALO_0p8x0p8_NETA = _FULLCALO_0p2x0p2_NETA - 3
      this_sum += _FULLCALO_0p2x0p2_MAP[ieta + 2][iphi];  // ieta + 2 is safe, since _FULLCALO_0p8x0p8_NETA = _FULLCALO_0p2x0p2_NETA - 3
      this_sum += _FULLCALO_0p2x0p2_MAP[ieta + 3][iphi];  // ieta + 3 is safe, since _FULLCALO_0p8x0p8_NETA = _FULLCALO_0p2x0p2_NETA - 3

      // add 1 to phi, but take modulus w.r.t. _FULLCALO_0p2x0p2_NPHI
      // in case we have wrapped back around
      this_sum += _FULLCALO_0p2x0p2_MAP[ieta][ ( iphi + 1 ) % _FULLCALO_0p2x0p2_NPHI ];
      this_sum += _FULLCALO_0p2x0p2_MAP[ieta + 1][ ( iphi + 1 ) % _FULLCALO_0p2x0p2_NPHI ];
      this_sum += _FULLCALO_0p2x0p2_MAP[ieta + 2][ ( iphi + 1 ) % _FULLCALO_0p2x0p2_NPHI ];
      this_sum += _FULLCALO_0p2x0p2_MAP[ieta + 3][ ( iphi + 1 ) % _FULLCALO_0p2x0p2_NPHI ];
      // add 2 to phi, but take modulus w.r.t. _FULLCALO_0p2x0p2_NPHI
      // in case we have wrapped back around
      this_sum += _FULLCALO_0p2x0p2_MAP[ieta][ ( iphi + 2 ) % _FULLCALO_0p2x0p2_NPHI ];
      this_sum += _FULLCALO_0p2x0p2_MAP[ieta + 1][ ( iphi + 2 ) % _FULLCALO_0p2x0p2_NPHI ];
      this_sum += _FULLCALO_0p2x0p2_MAP[ieta + 2][ ( iphi + 2 ) % _FULLCALO_0p2x0p2_NPHI ];
      this_sum += _FULLCALO_0p2x0p2_MAP[ieta + 3][ ( iphi + 2 ) % _FULLCALO_0p2x0p2_NPHI ];
      // add 3 to phi, but take modulus w.r.t. _FULLCALO_0p2x0p2_NPHI
      // in case we have wrapped back around
      this_sum += _FULLCALO_0p2x0p2_MAP[ieta][ ( iphi + 3 ) % _FULLCALO_0p2x0p2_NPHI ];
      this_sum += _FULLCALO_0p2x0p2_MAP[ieta + 1][ ( iphi + 3 ) % _FULLCALO_0p2x0p2_NPHI ];
      this_sum += _FULLCALO_0p2x0p2_MAP[ieta + 2][ ( iphi + 3 ) % _FULLCALO_0p2x0p2_NPHI ];
      this_sum += _FULLCALO_0p2x0p2_MAP[ieta + 3][ ( iphi + 3 ) % _FULLCALO_0p2x0p2_NPHI ];

      _FULLCALO_0p8x0p8_MAP[ieta][iphi] = this_sum;

      if (verbosity > 1 && this_sum > 4)
      {
        std::cout << "CaloTriggerSim::process_event: FullCalo  0.8x0.8 tower eta ( bin ) / phi ( bin ) / E = " << std::setprecision(6) << this_eta << " ( " << ieta << " ) / " << this_phi << " ( " << iphi << " ) / " << this_sum << std::endl;
      }

      if (this_sum > _FULLCALO_0p8x0p8_BEST_E)
      {
        _FULLCALO_0p8x0p8_BEST_E = this_sum;
        _FULLCALO_0p8x0p8_BEST_PHI = this_phi;
        _FULLCALO_0p8x0p8_BEST_ETA = this_eta;
      }
    }
  }

  if (verbosity > 0)
  {
    std::cout << "CaloTriggerSim::process_event: best FullCalo 0.8x0.8 window is at eta / phi = " << _FULLCALO_0p8x0p8_BEST_ETA << " / " << _FULLCALO_0p8x0p8_BEST_PHI << " and E = " << _FULLCALO_0p8x0p8_BEST_E << std::endl;
  }

  // reset fullcalo 1.0x1.0 map & best
  for (int ieta = 0; ieta < _FULLCALO_1p0x1p0_NETA; ieta++)
  {
    for (int iphi = 0; iphi < _FULLCALO_1p0x1p0_NPHI; iphi++)
    {
      _FULLCALO_1p0x1p0_MAP[ ieta ][ iphi ] = 0;
    }
  }

  _FULLCALO_1p0x1p0_BEST_E = 0;
  _FULLCALO_1p0x1p0_BEST_PHI = 0;
  _FULLCALO_1p0x1p0_BEST_ETA = 0;

  // now reconstruct (sliding) 1.0x1.0 map from 0.2x0.2 map
  for (int ieta = 0; ieta < _FULLCALO_1p0x1p0_NETA; ieta++)
  {
    for (int iphi = 0; iphi < _FULLCALO_1p0x1p0_NPHI; iphi++)
    {
      // for eta calculation, use position of corner tower and add 4.5
      // tower widths
      float this_eta = geomOH->get_etacenter(2 * ieta) + 4.5 * ( geomOH->get_etacenter( 1 ) - geomOH->get_etacenter( 0 ) );
      // for phi calculation, use position of corner tower and add 4.5
      // tower widths
      float this_phi = geomOH->get_phicenter(2 * iphi) + 4.5 * (geomOH->get_phicenter( 1 ) - geomOH->get_phicenter( 0 ) );

      float this_sum = 0;

      this_sum += _FULLCALO_0p2x0p2_MAP[ieta][iphi];
      this_sum += _FULLCALO_0p2x0p2_MAP[ieta + 1][iphi];  // ieta + 1 is safe, since _FULLCALO_1p0x1p0_NETA = _FULLCALO_0p2x0p2_NETA - 4
      this_sum += _FULLCALO_0p2x0p2_MAP[ieta + 2][iphi];  // ieta + 2 is safe, since _FULLCALO_1p0x1p0_NETA = _FULLCALO_0p2x0p2_NETA - 4
      this_sum += _FULLCALO_0p2x0p2_MAP[ieta + 3][iphi];  // ieta + 3 is safe, since _FULLCALO_1p0x1p0_NETA = _FULLCALO_0p2x0p2_NETA - 4
      this_sum += _FULLCALO_0p2x0p2_MAP[ieta + 4][iphi];  // ieta + 4 is safe, since _FULLCALO_1p0x1p0_NETA = _FULLCALO_0p2x0p2_NETA - 4

      // add 1 to phi, but take modulus w.r.t. _FULLCALO_0p2x0p2_NPHI
      // in case we have wrapped back around
      this_sum += _FULLCALO_0p2x0p2_MAP[ieta][ ( iphi + 1 ) % _FULLCALO_0p2x0p2_NPHI ];
      this_sum += _FULLCALO_0p2x0p2_MAP[ieta + 1][ ( iphi + 1 ) % _FULLCALO_0p2x0p2_NPHI ];
      this_sum += _FULLCALO_0p2x0p2_MAP[ieta + 2][ ( iphi + 1 ) % _FULLCALO_0p2x0p2_NPHI ];
      this_sum += _FULLCALO_0p2x0p2_MAP[ieta + 3][ ( iphi + 1 ) % _FULLCALO_0p2x0p2_NPHI ];
      this_sum += _FULLCALO_0p2x0p2_MAP[ieta + 4][ ( iphi + 1 ) % _FULLCALO_0p2x0p2_NPHI ];
      // add 2 to phi, but take modulus w.r.t. _FULLCALO_0p2x0p2_NPHI
      // in case we have wrapped back around
      this_sum += _FULLCALO_0p2x0p2_MAP[ieta][ ( iphi + 2 ) % _FULLCALO_0p2x0p2_NPHI ];
      this_sum += _FULLCALO_0p2x0p2_MAP[ieta + 1][ ( iphi + 2 ) % _FULLCALO_0p2x0p2_NPHI ];
      this_sum += _FULLCALO_0p2x0p2_MAP[ieta + 2][ ( iphi + 2 ) % _FULLCALO_0p2x0p2_NPHI ];
      this_sum += _FULLCALO_0p2x0p2_MAP[ieta + 3][ ( iphi + 2 ) % _FULLCALO_0p2x0p2_NPHI ];
      this_sum += _FULLCALO_0p2x0p2_MAP[ieta + 4][ ( iphi + 2 ) % _FULLCALO_0p2x0p2_NPHI ];
      // add 3 to phi, but take modulus w.r.t. _FULLCALO_0p2x0p2_NPHI
      // in case we have wrapped back around
      this_sum += _FULLCALO_0p2x0p2_MAP[ieta][ ( iphi + 3 ) % _FULLCALO_0p2x0p2_NPHI ];
      this_sum += _FULLCALO_0p2x0p2_MAP[ieta + 1][ ( iphi + 3 ) % _FULLCALO_0p2x0p2_NPHI ];
      this_sum += _FULLCALO_0p2x0p2_MAP[ieta + 2][ ( iphi + 3 ) % _FULLCALO_0p2x0p2_NPHI ];
      this_sum += _FULLCALO_0p2x0p2_MAP[ieta + 3][ ( iphi + 3 ) % _FULLCALO_0p2x0p2_NPHI ];
      this_sum += _FULLCALO_0p2x0p2_MAP[ieta + 4][ ( iphi + 3 ) % _FULLCALO_0p2x0p2_NPHI ];
      // add 4 to phi, but take modulus w.r.t. _FULLCALO_0p2x0p2_NPHI
      // in case we have wrapped back around
      this_sum += _FULLCALO_0p2x0p2_MAP[ieta][ ( iphi + 4 ) % _FULLCALO_0p2x0p2_NPHI ];
      this_sum += _FULLCALO_0p2x0p2_MAP[ieta + 1][ ( iphi + 4 ) % _FULLCALO_0p2x0p2_NPHI ];
      this_sum += _FULLCALO_0p2x0p2_MAP[ieta + 2][ ( iphi + 4 ) % _FULLCALO_0p2x0p2_NPHI ];
      this_sum += _FULLCALO_0p2x0p2_MAP[ieta + 3][ ( iphi + 4 ) % _FULLCALO_0p2x0p2_NPHI ];
      this_sum += _FULLCALO_0p2x0p2_MAP[ieta + 4][ ( iphi + 4 ) % _FULLCALO_0p2x0p2_NPHI ];

      _FULLCALO_1p0x1p0_MAP[ieta][iphi] = this_sum;

      if (verbosity > 1 && this_sum > 5)
      {
        std::cout << "CaloTriggerSim::process_event: FullCalo  1.0x1.0 tower eta ( bin ) / phi ( bin ) / E = " << std::setprecision(6) << this_eta << " ( " << ieta << " ) / " << this_phi << " ( " << iphi << " ) / " << this_sum << std::endl;
      }

      if (this_sum > _FULLCALO_1p0x1p0_BEST_E)
      {
        _FULLCALO_1p0x1p0_BEST_E = this_sum;
        _FULLCALO_1p0x1p0_BEST_PHI = this_phi;
        _FULLCALO_1p0x1p0_BEST_ETA = this_eta;
      }
    }
  }

  if (verbosity > 0)
  {
    std::cout << "CaloTriggerSim::process_event: best FullCalo 1.0x1.0 window is at eta / phi = " << _FULLCALO_1p0x1p0_BEST_ETA << " / " << _FULLCALO_1p0x1p0_BEST_PHI << " and E = " << _FULLCALO_1p0x1p0_BEST_E << std::endl;
  }



  FillNode(topNode);

  if (verbosity > 0) std::cout << "CaloTriggerSim::process_event: exiting" << std::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;
}
Beispiel #5
0
std::vector<Jet*> TowerJetInput::get_input(PHCompositeNode *topNode) {
  
  if (_verbosity > 0) cout << "TowerJetInput::process_event -- entered" << endl;

  GlobalVertexMap* vertexmap = findNode::getClass<GlobalVertexMap>(topNode,"GlobalVertexMap");
  if (!vertexmap) {

    cout <<"TowerJetInput::get_input - Fatal Error - GlobalVertexMap node is missing. Please turn on the do_global flag in the main macro in order to reconstruct the global vertex."<<endl;
    assert(vertexmap); // force quit

    return std::vector<Jet*>();
  }

  RawTowerContainer *towers = NULL;
  RawTowerGeomContainer *geom = NULL;
  if (_input == Jet::CEMC_TOWER) {
    towers = findNode::getClass<RawTowerContainer>(topNode,"TOWER_CALIB_CEMC");
    geom = findNode::getClass<RawTowerGeomContainer>(topNode,"TOWERGEOM_CEMC");
    if (!towers||!geom) {
      return std::vector<Jet*>();
    }
  } else if (_input == Jet::HCALIN_TOWER) {
    towers = findNode::getClass<RawTowerContainer>(topNode,"TOWER_CALIB_HCALIN");
    geom = findNode::getClass<RawTowerGeomContainer>(topNode,"TOWERGEOM_HCALIN");
    if (!towers||!geom) {
      return std::vector<Jet*>();
    }
  } else if (_input == Jet::HCALOUT_TOWER) {
    towers = findNode::getClass<RawTowerContainer>(topNode,"TOWER_CALIB_HCALOUT");
    geom = findNode::getClass<RawTowerGeomContainer>(topNode,"TOWERGEOM_HCALOUT");
    if (!towers||!geom) {
      return std::vector<Jet*>();
    }
  } else if (_input == Jet::FEMC_TOWER) {
    towers = findNode::getClass<RawTowerContainer>(topNode,"TOWER_CALIB_FEMC");
    geom = findNode::getClass<RawTowerGeomContainer>(topNode,"TOWERGEOM_FEMC");
    if (!towers||!geom) {
      return std::vector<Jet*>();
    }
  } else if (_input == Jet::FHCAL_TOWER) {
    towers = findNode::getClass<RawTowerContainer>(topNode,"TOWER_CALIB_FHCAL");
    geom = findNode::getClass<RawTowerGeomContainer>(topNode,"TOWERGEOM_FHCAL");
    if (!towers||!geom) {
      return std::vector<Jet*>();
    }
  } else if (_input == Jet::CEMC_TOWER_SUB1) {
    towers = findNode::getClass<RawTowerContainer>(topNode,"TOWER_CALIB_CEMC_RETOWER_SUB1");
    geom = findNode::getClass<RawTowerGeomContainer>(topNode,"TOWERGEOM_HCALIN");
    if (!towers||!geom) {
      return std::vector<Jet*>();
    }
  } else if (_input == Jet::HCALIN_TOWER_SUB1) {
    towers = findNode::getClass<RawTowerContainer>(topNode,"TOWER_CALIB_HCALIN_SUB1");
    geom = findNode::getClass<RawTowerGeomContainer>(topNode,"TOWERGEOM_HCALIN");
    if (!towers||!geom) {
      return std::vector<Jet*>();
    }
  } else if (_input == Jet::HCALOUT_TOWER_SUB1) {
    towers = findNode::getClass<RawTowerContainer>(topNode,"TOWER_CALIB_HCALOUT_SUB1");
    geom = findNode::getClass<RawTowerGeomContainer>(topNode,"TOWERGEOM_HCALOUT");
    if (!towers||!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*>();

  if (isnan(vtxz))
    {
      static bool once = true;
      if (once)
        {
          once = false;

          cout <<"TowerJetInput::get_input - WARNING - vertex is NAN. Drop all tower inputs (further NAN-vertex warning will be suppressed)."<<endl;
        }

      return std::vector<Jet*>();
    }

  std::vector<Jet*> pseudojets;
  RawTowerContainer::ConstRange begin_end = towers->getTowers();
  RawTowerContainer::ConstIterator rtiter;
  for (rtiter = begin_end.first; rtiter !=  begin_end.second; ++rtiter) {
    RawTower *tower = rtiter->second;

    RawTowerGeom * tower_geom =
    geom->get_tower_geometry(tower -> get_key());
    assert(tower_geom);

    double r = tower_geom->get_center_radius();
    double phi = atan2(tower_geom->get_center_y(), tower_geom->get_center_x());
    double z0 = tower_geom->get_center_z();

    double z = z0 - vtxz;
    
    double eta = asinh(z/r); // eta after shift from vertex

    double pt = tower->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(tower->get_energy());
    jet->insert_comp(_input,tower->get_id());

    pseudojets.push_back(jet);
  }

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

  return pseudojets;
}
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 EventInfoSummary::process_event(PHCompositeNode* topNode)
{
  Event* event = findNode::getClass<Event>(topNode, "PRDF");
  if (event == NULL)
  {
    if (Verbosity() >= VERBOSITY_SOME)
      cout << "EventInfoSummary::Process_Event - Event not found" << endl;
    return Fun4AllReturnCodes::DISCARDEVENT;
  }

  // search for run info
  if (event->getEvtType() != DATAEVENT)
    return Fun4AllReturnCodes::EVENT_OK;
  else  // DATAEVENT
  {
    if (verbosity >= VERBOSITY_SOME)
    {
      cout << "EventInfoSummary::process_event - with DATAEVENT events ";
      event->identify();
    }

    map<int, Packet*> packet_list;

    PHParameters Params("EventInfo");

    // spill indicator
    {
      RawTowerContainer* TOWER_RAW_SPILL_WARBLER = findNode::getClass<
          RawTowerContainer>(topNode, "TOWER_RAW_SPILL_WARBLER");
      assert(TOWER_RAW_SPILL_WARBLER);

      RawTower_Prototype4* raw_tower =
          dynamic_cast<RawTower_Prototype4*>(TOWER_RAW_SPILL_WARBLER->getTower(0));
      assert(raw_tower);

      accumulator_set<double, features<tag::variance>> acc;

      vector<double> vec_signal_samples;
      for (int i = 0; i < RawTower_Prototype4::NSAMPLES; i++)
      {
        acc(raw_tower->get_signal_samples(i));
      }

      const double warbler_rms = variance(acc);
      const bool is_in_spill = warbler_rms > (1000 * 1000);
      Params.set_double_param("beam_SPILL_WARBLER_RMS", warbler_rms);
      Params.set_double_param("beam_Is_In_Spill", is_in_spill);
      Params.set_int_param("beam_Is_In_Spill", is_in_spill);
    }

    // energy sums
    {
      RawTowerContainer* TOWER_CALIB_CEMC = findNode::getClass<
          RawTowerContainer>(topNode, "TOWER_CALIB_CEMC");
      assert(TOWER_CALIB_CEMC);

      RawTowerContainer* TOWER_CALIB_LG_HCALIN = findNode::getClass<
          RawTowerContainer>(topNode, "TOWER_CALIB_LG_HCALIN");

      RawTowerContainer* TOWER_CALIB_LG_HCALOUT = findNode::getClass<
          RawTowerContainer>(topNode, "TOWER_CALIB_LG_HCALOUT");

      // process inner HCAL
      if (TOWER_CALIB_CEMC)
      {
        double sum_energy_calib = 0;

        auto range = TOWER_CALIB_CEMC->getTowers();
        for (auto it = range.first; it != range.second; ++it)
        {
          RawTower* tower = it->second;
          assert(tower);

          const int col = tower->get_bineta();
          const int row = tower->get_binphi();

          if (col < 0 or col >= 8)
            continue;
          if (row < 0 or row >= 8)
            continue;

          const double energy_calib = tower->get_energy();
          sum_energy_calib += energy_calib;

        }  //       for (auto it = range.first; it != range.second; ++it)
        Params.set_double_param("CALIB_CEMC_Sum", sum_energy_calib);
      }  // process inner HCAL

      // process inner HCAL
      if (TOWER_CALIB_LG_HCALIN)
      {
        double sum_energy_calib = 0;

        auto range = TOWER_CALIB_LG_HCALIN->getTowers();
        for (auto it = range.first; it != range.second; ++it)
        {
          RawTower* tower = it->second;
          assert(tower);

          const int col = tower->get_bineta();
          const int row = tower->get_binphi();

          if (col < 0 or col >= 4)
            continue;
          if (row < 0 or row >= 4)
            continue;

          const double energy_calib = tower->get_energy();
          sum_energy_calib += energy_calib;

        }  //       for (auto it = range.first; it != range.second; ++it)
        Params.set_double_param("CALIB_LG_HCALIN_Sum", sum_energy_calib);
      }  // process inner HCAL

      // process outer HCAL
      if (TOWER_CALIB_LG_HCALOUT)
      {
        double sum_energy_calib = 0;

        auto range = TOWER_CALIB_LG_HCALOUT->getTowers();
        for (auto it = range.first; it != range.second; ++it)
        {
          RawTower* tower = it->second;
          assert(tower);

          const int col = tower->get_bineta();
          const int row = tower->get_binphi();

          if (col < 0 or col >= 4)
            continue;
          if (row < 0 or row >= 4)
            continue;

          const double energy_calib = tower->get_energy();
          sum_energy_calib += energy_calib;

        }  //       for (auto it = range.first; it != range.second; ++it)

        Params.set_double_param("CALIB_LG_HCALOUT_Sum", sum_energy_calib);
      }  // process outer HCAL
    }

    // generic packets
    for (typ_channel_map::const_iterator it = channel_map.begin();
         it != channel_map.end(); ++it)
    {
      const string& name = it->first;
      const channel_info& info = it->second;

      if (packet_list.find(info.packet_id) == packet_list.end())
      {
        packet_list[info.packet_id] = event->getPacket(info.packet_id);
      }

      Packet* packet = packet_list[info.packet_id];

      if (!packet)
      {
        //          if (Verbosity() >= VERBOSITY_SOME)
        cout
            << "EventInfoSummary::process_event - failed to locate packet "
            << info.packet_id << " from ";
        event->identify();

        Params.set_double_param(name, NAN);
        continue;
      }

      const int ivalue = packet->iValue(info.offset);

      const double dvalue = ivalue * info.calibration_const;

      if (verbosity >= VERBOSITY_SOME)
      {
        cout << "EventInfoSummary::process_event - " << name << " = "
             << dvalue << ", raw = " << ivalue << " @ packet "
             << info.packet_id << ", offset " << info.offset << endl;
      }

      Params.set_double_param(name, dvalue);
    }

    for (map<int, Packet*>::iterator it = packet_list.begin();
         it != packet_list.end(); ++it)
    {
      if (it->second)
        delete it->second;
    }

    Params.SaveToNodeTree(topNode, eventinfo_node_name);

    if (verbosity >= VERBOSITY_SOME)
      Params.Print();
  }
  return Fun4AllReturnCodes::EVENT_OK;
}
float
TrackProjectionTools::getE33Forward( string detName, float tkx, float tky )
{
  float twr_sum = 0;

  string towernodename = "TOWER_CALIB_" + detName;
  // Grab the towers
  RawTowerContainer* towers = findNode::getClass<RawTowerContainer>(_topNode, towernodename.c_str());
  if (!towers)
    {
      std::cout << PHWHERE << ": Could not find node " << towernodename.c_str() << std::endl;
      return -1;
    }
  string towergeomnodename = "TOWERGEOM_" + detName;
  RawTowerGeomContainer *towergeom = findNode::getClass<RawTowerGeomContainer>(_topNode, towergeomnodename.c_str());
  if (! towergeom)
    {
      cout << PHWHERE << ": Could not find node " << towergeomnodename.c_str() << endl;
      return -1;
    }

  // Locate the central tower
  float r_dist = 9999.0;
  int twr_j = -1;
  int twr_k = -1;
  RawTowerDefs::CalorimeterId calo_id_ = RawTowerDefs::convert_name_to_caloid( detName );

  RawTowerContainer::ConstRange begin_end  = towers->getTowers();
  RawTowerContainer::ConstIterator itr = begin_end.first;
  for (; itr != begin_end.second; ++itr)
    {
      RawTowerDefs::keytype towerid = itr->first;
      RawTowerGeom *tgeo = towergeom->get_tower_geometry(towerid);

      float x = tgeo->get_center_x();
      float y = tgeo->get_center_y();

      float temp_rdist = sqrt(pow(tkx-x,2) + pow(tky-y,2)) ;
      if(temp_rdist< r_dist){
        r_dist = temp_rdist;
        twr_j = RawTowerDefs::decode_index1(towerid);
        twr_k = RawTowerDefs::decode_index2(towerid);
      }

      if( (fabs(tkx-x)<(tgeo->get_size_x()/2.0)) &&
          (fabs(tky-y)<(tgeo->get_size_y()/2.0)) ) break;

    }

  // Use the central tower to sum up the 3x3 energy
  if(twr_j>=0 && twr_k>=0){
    for(int ij = -1; ij <=1; ij++){
      for(int ik = -1; ik <=1; ik++){
        RawTowerDefs::keytype temp_towerid = RawTowerDefs::encode_towerid( calo_id_ , twr_j + ij , twr_k + ik );
        RawTower *rawtower = towers->getTower(temp_towerid);
        if(rawtower) twr_sum += rawtower->get_energy();
      }
    }
  }

  return twr_sum;
}
int
Proto2ShowerCalib::process_event(PHCompositeNode *topNode)
{

  if (verbosity > 2)
    cout << "Proto2ShowerCalib::process_event() entered" << endl;

  // init eval objects
  _eval_run.reset();
  _shower.reset();

  Fun4AllHistoManager *hm = get_HistoManager();
  assert(hm);

  PdbParameterMap *info = findNode::getClass<PdbParameterMap>(topNode,
      "RUN_INFO");

  //if(!_is_sim) assert(info);
 
  if(info)
  {
   PHParameters run_info_copy("RunInfo");
   run_info_copy.FillFrom(info);

   _eval_run.beam_mom = run_info_copy.get_double_param("beam_MTNRG_GeV");

   TH1F * hBeam_Mom = dynamic_cast<TH1F *>(hm->getHisto("hBeam_Mom"));
   assert(hBeam_Mom);

   hBeam_Mom->Fill(_eval_run.beam_mom);
  }

  EventHeader* eventheader = findNode::getClass<EventHeader>(topNode,
      "EventHeader");
  //if(!_is_sim) assert(eventheader);

  if( eventheader )
  {
   _eval_run.run = eventheader->get_RunNumber();
   if (verbosity > 4)
    cout << __PRETTY_FUNCTION__ << _eval_run.run << endl;

   _eval_run.event = eventheader->get_EvtSequence();
  }
  // normalization
  TH1F * hNormalization = dynamic_cast<TH1F *>(hm->getHisto("hNormalization"));
  assert(hNormalization);

  hNormalization->Fill("ALL", 1);

  // other nodes
  RawTowerContainer* TOWER_CALIB_TRIGGER_VETO = findNode::getClass<
      RawTowerContainer>(topNode, "TOWER_CALIB_TRIGGER_VETO");
  //if(!_is_sim) assert(TOWER_CALIB_TRIGGER_VETO);

  RawTowerContainer* TOWER_CALIB_HODO_HORIZONTAL = findNode::getClass<
      RawTowerContainer>(topNode, "TOWER_CALIB_HODO_HORIZONTAL");
  //if(!_is_sim) assert(TOWER_CALIB_HODO_HORIZONTAL);

  RawTowerContainer* TOWER_CALIB_HODO_VERTICAL = findNode::getClass<
      RawTowerContainer>(topNode, "TOWER_CALIB_HODO_VERTICAL");
  //if(!_is_sim) assert(TOWER_CALIB_HODO_VERTICAL);

 RawTowerContainer* TOWER_RAW_CEMC;
  if(!_is_sim) 
  {
   TOWER_RAW_CEMC = findNode::getClass<RawTowerContainer>(
      topNode, "TOWER_RAW_CEMC");
  }else{
   TOWER_RAW_CEMC = findNode::getClass<RawTowerContainer>(
      topNode, "TOWER_RAW_LG_CEMC");
 }
  assert(TOWER_RAW_CEMC);

 RawTowerContainer* TOWER_CALIB_CEMC;
 if(!_is_sim)
 {
  TOWER_CALIB_CEMC = findNode::getClass<RawTowerContainer>(
      topNode, "TOWER_CALIB_CEMC");
 } else {
  TOWER_CALIB_CEMC = findNode::getClass<RawTowerContainer>(
      topNode, "TOWER_CALIB_LG_CEMC");
 }
  assert(TOWER_CALIB_CEMC);

  RawTowerContainer* TOWER_RAW_LG_HCALIN = 0;
  RawTowerContainer* TOWER_RAW_HG_HCALIN = 0;
  if(!_is_sim)
  {
   TOWER_RAW_LG_HCALIN = findNode::getClass<RawTowerContainer>(
      topNode, "TOWER_RAW_LG_HCALIN");
   TOWER_RAW_HG_HCALIN= findNode::getClass<RawTowerContainer>(
      topNode, "TOWER_RAW_HG_HCALIN");
   assert(TOWER_RAW_LG_HCALIN);
   assert(TOWER_RAW_HG_HCALIN);
  }

  RawTowerContainer* TOWER_CALIB_HCALIN;
  if(!_is_sim)
  {
   TOWER_CALIB_HCALIN = findNode::getClass<RawTowerContainer>(
      topNode, "TOWER_CALIB_LG_HCALIN");
  } else {
   TOWER_CALIB_HCALIN = findNode::getClass<RawTowerContainer>(
      topNode, "TOWER_CALIB_LG_HCALIN");
  }
  assert(TOWER_CALIB_HCALIN);

  RawTowerContainer* TOWER_RAW_LG_HCALOUT = 0;
  RawTowerContainer* TOWER_RAW_HG_HCALOUT = 0;
  if(!_is_sim)
  {
   TOWER_RAW_LG_HCALOUT = findNode::getClass<RawTowerContainer>(
      topNode, "TOWER_RAW_LG_HCALOUT");
   TOWER_RAW_HG_HCALOUT = findNode::getClass<RawTowerContainer>(
      topNode, "TOWER_RAW_HG_HCALOUT");
   assert(TOWER_RAW_LG_HCALOUT);
   assert(TOWER_RAW_HG_HCALOUT);
  }

  RawTowerContainer* TOWER_CALIB_HCALOUT = findNode::getClass<RawTowerContainer>(
      topNode, "TOWER_CALIB_LG_HCALOUT");
  assert(TOWER_CALIB_HCALOUT);

  RawTowerContainer* TOWER_TEMPERATURE_EMCAL = findNode::getClass<
      RawTowerContainer>(topNode, "TOWER_TEMPERATURE_EMCAL");
  if(!_is_sim) assert(TOWER_TEMPERATURE_EMCAL);

  RawTowerContainer* TOWER_CALIB_C1 = findNode::getClass<RawTowerContainer>(
      topNode, "TOWER_CALIB_C1");
  //if(!_is_sim) assert(TOWER_CALIB_C1);
  RawTowerContainer* TOWER_CALIB_C2 = findNode::getClass<RawTowerContainer>(
      topNode, "TOWER_CALIB_C2");
  //if(!_is_sim) assert(TOWER_CALIB_C2);

  if(!_is_sim && TOWER_CALIB_C2 && TOWER_CALIB_C1 && eventheader)
  {
  // Cherenkov
  RawTower * t_c2_in = NULL;
  RawTower * t_c2_out = NULL;

  if (eventheader->get_RunNumber() >= 2105)
    {
      t_c2_in = TOWER_CALIB_C2->getTower(10);
      t_c2_out = TOWER_CALIB_C2->getTower(11);
    }
  else
    {
      t_c2_in = TOWER_CALIB_C2->getTower(0);
      t_c2_out = TOWER_CALIB_C2->getTower(1);
    }
  assert(t_c2_in);
  assert(t_c2_out);

  const double c2_in = t_c2_in->get_energy();
  const double c2_out = t_c2_out->get_energy();
  const double c1 = TOWER_CALIB_C1->getTower(0)->get_energy();

  _eval_run.C2_sum = c2_in + c2_out;
  _eval_run.C1 = c1;
  bool cherekov_e = (_eval_run.C2_sum) > 100;
  hNormalization->Fill("C2-e", cherekov_e);

  bool cherekov_h = (_eval_run.C2_sum) < 20;
  hNormalization->Fill("C2-h", cherekov_h);

  TH2F * hCheck_Cherenkov = dynamic_cast<TH2F *>(hm->getHisto(
      "hCheck_Cherenkov"));
  assert(hCheck_Cherenkov);
  hCheck_Cherenkov->Fill(c1, "C1", 1);
  hCheck_Cherenkov->Fill(c2_in, "C2 in", 1);
  hCheck_Cherenkov->Fill(c2_out, "C2 out", 1);
  hCheck_Cherenkov->Fill(c2_in + c2_out, "C2 sum", 1);

  // veto
  TH1F * hCheck_Veto = dynamic_cast<TH1F *>(hm->getHisto("hCheck_Veto"));
  assert(hCheck_Veto);
  bool trigger_veto_pass = true;
    {
      auto range = TOWER_CALIB_TRIGGER_VETO->getTowers();
      for (auto it = range.first; it != range.second; ++it)
        {
          RawTower* tower = it->second;
          assert(tower);

          hCheck_Veto->Fill(tower->get_energy());

          if (abs(tower->get_energy()) > 15)
            trigger_veto_pass = false;
        }
    }
  hNormalization->Fill("trigger_veto_pass", trigger_veto_pass);
  _eval_run.trigger_veto_pass = trigger_veto_pass;

  // hodoscope
  TH1F * hCheck_Hodo_H = dynamic_cast<TH1F *>(hm->getHisto("hCheck_Hodo_H"));
  assert(hCheck_Hodo_H);
  int hodo_h_count = 0;
    {
      auto range = TOWER_CALIB_HODO_HORIZONTAL->getTowers();
      for (auto it = range.first; it != range.second; ++it)
        {
          RawTower* tower = it->second;
          assert(tower);
          hCheck_Hodo_H->Fill(tower->get_energy());

          if (abs(tower->get_energy()) > 30)
            {
              hodo_h_count++;
              _eval_run.hodo_h = tower->get_id();
            }
        }
    }

  const bool valid_hodo_h = hodo_h_count == 1;
  hNormalization->Fill("valid_hodo_h", valid_hodo_h);
  _eval_run.valid_hodo_h = valid_hodo_h;

  TH1F * hCheck_Hodo_V = dynamic_cast<TH1F *>(hm->getHisto("hCheck_Hodo_V"));
  assert(hCheck_Hodo_V);
  int hodo_v_count = 0;
   {
      auto range = TOWER_CALIB_HODO_VERTICAL->getTowers();
      for (auto it = range.first; it != range.second; ++it)
        {
          RawTower* tower = it->second;
          assert(tower);

          hCheck_Hodo_V->Fill(tower->get_energy());

          if (abs(tower->get_energy()) > 30)
            {
              hodo_v_count++;
              _eval_run.hodo_v = tower->get_id();
            }
        }
    }
  const bool valid_hodo_v = hodo_v_count == 1;
  _eval_run.valid_hodo_v = valid_hodo_v;
  hNormalization->Fill("valid_hodo_v", valid_hodo_v);

  const bool good_e = valid_hodo_v and valid_hodo_h and cherekov_e and trigger_veto_pass;

  const bool good_h = valid_hodo_v and valid_hodo_h and cherekov_h and trigger_veto_pass;

  hNormalization->Fill("good_e", good_e);
  hNormalization->Fill("good_h", good_h);

  _eval_run.good_temp = 1;
  _eval_run.good_e = good_e;
  _eval_run.good_h = good_h;

  }
  // tower
  double emcal_sum_energy_calib = 0;
  double emcal_sum_energy_recalib = 0;

  double hcalin_sum_energy_calib = 0;
  double hcalin_sum_energy_recalib = 0;

  double hcalout_sum_energy_calib = 0;
  double hcalout_sum_energy_recalib = 0;

  stringstream sdata;

   //EMCAL towers
    {
      auto range = TOWER_CALIB_CEMC->getTowers();
      for (auto it = range.first; it != range.second; ++it)
        {

          //RawTowerDefs::keytype key = it->first;
          RawTower* tower = it->second;
          assert(tower);

          const double energy_calib = tower->get_energy();
          emcal_sum_energy_calib += energy_calib;
           
          if(_is_sim) continue;
          const int col = tower->get_column();
          const int row = tower->get_row();

          // recalibration
          assert(
              _emcal_recalib_const.find(make_pair(col, row)) != _emcal_recalib_const.end());
          const double energy_recalib = energy_calib
              * _emcal_recalib_const[make_pair(col, row)];

          // energy sums
          emcal_sum_energy_recalib += energy_recalib;
         }
      }

  //HCALIN towers
  {
      auto range = TOWER_CALIB_HCALIN->getTowers();
      for (auto it = range.first; it != range.second; ++it)
        {
          RawTower* tower = it->second;
          assert(tower);

          const double energy_calib = tower->get_energy();
          hcalin_sum_energy_calib += energy_calib;

          if(_is_sim) continue;
          const int col = tower->get_column();
          const int row = tower->get_row();

          assert(
              _hcalin_recalib_const.find(make_pair(col, row)) != _hcalin_recalib_const.end());
          const double energy_recalib = energy_calib
              * _hcalin_recalib_const[make_pair(col, row)];

          hcalin_sum_energy_recalib += energy_recalib;
         }
     }
  
   //HCALOUT towers
   {
      auto range = TOWER_CALIB_HCALOUT->getTowers();
      for (auto it = range.first; it != range.second; ++it)
        {
          RawTower* tower = it->second;
          assert(tower);

          const double energy_calib = tower->get_energy();
          hcalout_sum_energy_calib += energy_calib;
           
          if(_is_sim) continue;
          const int col = tower->get_column();
          const int row = tower->get_row();

          assert(
              _hcalout_recalib_const.find(make_pair(col, row)) != _hcalout_recalib_const.end());
          const double energy_recalib = energy_calib
              * _hcalout_recalib_const[make_pair(col, row)];
               
              hcalout_sum_energy_recalib += energy_recalib;
         }
     }

  const double EoP = emcal_sum_energy_recalib / abs(_eval_run.beam_mom);
  _eval_run.EoP = EoP;

  // E/p
  if (_eval_run.good_e)
    {
      if (verbosity >= 3)
        cout << __PRETTY_FUNCTION__ << " sum_energy_calib = "
            << emcal_sum_energy_calib << " sum_energy_recalib = " << emcal_sum_energy_recalib
            << " _eval_run.beam_mom = " << _eval_run.beam_mom << endl;

      TH2F * hEoP = dynamic_cast<TH2F *>(hm->getHisto("hEoP"));
      assert(hEoP);

      hEoP->Fill(EoP, abs(_eval_run.beam_mom));
    }

  // calibration file
   assert(fdata.is_open());
   fdata << sdata.str();
   fdata << endl;

  _shower.emcal_e = emcal_sum_energy_calib;
  _shower.hcalin_e = hcalin_sum_energy_calib;
  _shower.hcalout_e = hcalout_sum_energy_calib;
  _shower.sum_e = emcal_sum_energy_calib + hcalin_sum_energy_calib + hcalout_sum_energy_calib ;
  _shower.hcal_asym = (hcalin_sum_energy_calib - hcalout_sum_energy_calib)/(hcalin_sum_energy_calib + hcalout_sum_energy_calib);

  _shower.emcal_e_recal = emcal_sum_energy_recalib;
  _shower.hcalin_e_recal = hcalin_sum_energy_recalib;
  _shower.hcalout_e_recal = hcalout_sum_energy_recalib;
  _shower.sum_e_recal = emcal_sum_energy_recalib + hcalin_sum_energy_recalib + hcalout_sum_energy_recalib ;

  
  if(_fill_time_samples && !_is_sim)
  {
   //HCALIN
   {
    auto range = TOWER_RAW_LG_HCALIN->getTowers();
    for (auto it = range.first; it != range.second; ++it)
    {
      RawTower_Prototype2* tower = dynamic_cast<RawTower_Prototype2 *>(it->second);
      assert(tower);

      int col = tower->get_column();
      int row = tower->get_row();
      int towerid = row + 4*col;
      for(int isample=0; isample<24; isample++)
       _time_samples.hcalin_time_samples[towerid][isample] =
                tower->get_signal_samples(isample);

     }
    }

   //HCALOUT
   {
    auto range = TOWER_RAW_LG_HCALOUT->getTowers();
    for (auto it = range.first; it != range.second; ++it)
    {
      RawTower_Prototype2* tower = dynamic_cast<RawTower_Prototype2 *>(it->second);
      assert(tower);

      int col = tower->get_column();
      int row = tower->get_row();
      int towerid = row + 4*col;
      for(int isample=0; isample<24; isample++) 
       _time_samples.hcalout_time_samples[towerid][isample] = 
		tower->get_signal_samples(isample);

     }
    }

   //EMCAL
   {
    auto range = TOWER_RAW_CEMC->getTowers();
    for (auto it = range.first; it != range.second; ++it)
    {
      RawTower_Prototype2* tower = dynamic_cast<RawTower_Prototype2 *>(it->second);
      assert(tower);

      int col = tower->get_column();
      int row = tower->get_row();
      int towerid = row + 8*col;
      for(int isample=0; isample<24; isample++)
       _time_samples.emcal_time_samples[towerid][isample] =
                tower->get_signal_samples(isample);

     }
    }
  }

  TTree * T = dynamic_cast<TTree *>(hm->getHisto("T"));
  assert(T);
  T->Fill();

  return Fun4AllReturnCodes::EVENT_OK;
}
int
LeptoquarksReco::AddJetStructureInformation( type_map_tcan& tauCandidateMap, type_map_cdata* map_towers )
{
  /* Cone size around jet axis within which to look for tracks */
  float delta_R_cutoff_r1 = 0.1;
  float delta_R_cutoff_r2 = 0.2;
  float delta_R_cutoff_r3 = 0.3;
  float delta_R_cutoff_r4 = 0.4;
  float delta_R_cutoff_r5 = 0.5;

  /* energy threshold for considering tower */
  float tower_emin = 0.0;

  /* number of steps for finding r90 */
  int n_steps = 50;

  /* Loop over tau candidates */
  for (type_map_tcan::iterator iter = tauCandidateMap.begin();
       iter != tauCandidateMap.end();
       ++iter)
    {
      /* get jet axis */
      float jet_eta = (iter->second)->get_property_float( PidCandidate::jet_eta );
      float jet_phi = (iter->second)->get_property_float( PidCandidate::jet_phi );
      float jet_e =   (iter->second)->get_property_float( PidCandidate::jet_etotal );

      /* collect jet structure properties */
      float er1 = 0;
      float er2 = 0;
      float er3 = 0;
      float er4 = 0;
      float er5 = 0;
      float r90 = 0;
      float radius = 0;
      float rms = 0;
      float rms_esum = 0;

      /* collect jet structure properties- EMCal ONLY */
      float emcal_er1 = 0;
      float emcal_er2 = 0;
      float emcal_er3 = 0;
      float emcal_er4 = 0;
      float emcal_er5 = 0;
      float emcal_r90 = 0;
      float emcal_radius = 0;
      float emcal_rms = 0;
      float emcal_rms_esum = 0;

      /* Loop over all tower (and geometry) collections */
      for (type_map_cdata::iterator iter_calo = map_towers->begin();
           iter_calo != map_towers->end();
           ++iter_calo)
        {
          /* define tower iterator */
          RawTowerContainer::ConstRange begin_end = ((iter_calo->second).first)->getTowers();
          RawTowerContainer::ConstIterator rtiter;

          /* loop over all tower in CEMC calorimeter */
          for (rtiter = begin_end.first; rtiter !=  begin_end.second; ++rtiter)
            {
              /* get tower energy */
              RawTower *tower = rtiter->second;
              float tower_energy = tower->get_energy();

              /* check if tower above energy treshold */
              if ( tower_energy < tower_emin )
                continue;

              /* get eta and phi of tower and check angle delta_R w.r.t. jet axis */
              RawTowerGeom * tower_geom = ((iter_calo->second).second)->get_tower_geometry(tower -> get_key());
              float tower_eta = tower_geom->get_eta();
              float tower_phi = tower_geom->get_phi();

              /* If accounting for displaced vertex, need to calculate eta and phi:
                 double r = tower_geom->get_center_radius();
                 double phi = atan2(tower_geom->get_center_y(), tower_geom->get_center_x());
                 double z0 = tower_geom->get_center_z();
                 double z = z0 - vtxz;
                 double eta = asinh(z/r); // eta after shift from vertex
              */

              float delta_R = CalculateDeltaR( tower_eta , tower_phi, jet_eta, jet_phi );

              /* if save_towers set true: add tower to tree */
              if ( _save_towers )
                {
                  float tower_data[17] = {(float) _ievent,
                                          (float) (iter->second)->get_property_uint( PidCandidate::jet_id ),
                                          (float) (iter->second)->get_property_int( PidCandidate::evtgen_pid ),
                                          (float) (iter->second)->get_property_float( PidCandidate::evtgen_etotal ),
                                          (float) (iter->second)->get_property_float( PidCandidate::evtgen_eta ),
                                          (float) (iter->second)->get_property_float( PidCandidate::evtgen_phi ),
                                          (float) (iter->second)->get_property_uint( PidCandidate::evtgen_decay_prong ),
                                          (float) (iter->second)->get_property_uint( PidCandidate::evtgen_decay_hcharged ),
                                          (float) (iter->second)->get_property_uint( PidCandidate::evtgen_decay_lcharged ),
                                          (float) (iter->second)->get_property_float( PidCandidate::jet_eta ),
                                          (float) (iter->second)->get_property_float( PidCandidate::jet_phi ),
                                          (float) (iter->second)->get_property_float( PidCandidate::jet_etotal ),
                                          (float) (iter_calo->first),
                                          (float) tower_eta,
                                          (float) tower_phi,
                                          (float) delta_R,
                                          (float) tower_energy
                  };

                  _ntp_tower->Fill(tower_data);
                }

              /* check delta R distance tower from jet axis */
              if ( delta_R <= delta_R_cutoff_r1 )
                {
                  er1 += tower_energy;
                  if ( (iter_calo->first) == RawTowerDefs::CEMC )
                    emcal_er1 += tower_energy;
                }
              if ( delta_R <= delta_R_cutoff_r2 )
                {
                  er2 += tower_energy;
                  if ( (iter_calo->first) == RawTowerDefs::CEMC )
                    emcal_er2 += tower_energy;
                }
              if ( delta_R <= delta_R_cutoff_r3 )
                {
                  er3 += tower_energy;
                  if ( (iter_calo->first) == RawTowerDefs::CEMC )
                    emcal_er3 += tower_energy;
                }
              if ( delta_R <= delta_R_cutoff_r4 )
                {
                  er4 += tower_energy;
                  if ( (iter_calo->first) == RawTowerDefs::CEMC )
                    emcal_er4 += tower_energy;
                }
              if ( delta_R <= delta_R_cutoff_r5 )
                {
                  er5 += tower_energy;
                  if ( (iter_calo->first) == RawTowerDefs::CEMC )
                    emcal_er5 += tower_energy;
                }

              if ( delta_R <= delta_R_cutoff_r5 )
                {
                  rms += tower_energy*delta_R*delta_R;
                  rms_esum += tower_energy;

                  radius += tower_energy*delta_R;

                  if ( (iter_calo->first) == RawTowerDefs::CEMC )
                    {
                      emcal_rms += tower_energy*delta_R*delta_R;
                      emcal_rms_esum += tower_energy;
                      emcal_radius += tower_energy*delta_R;
                    }
                }
            }
        }

      /* finalize calculation of rms and radius */
      if ( rms_esum > 0 )
        {
          radius /= rms_esum;
          rms    /= rms_esum;
          rms     = sqrt( rms );
        }
      else
        {
          radius = -1;
          rms = -1;
        }
      if ( emcal_rms_esum > 0 )
        {
          emcal_radius /= emcal_rms_esum;
          emcal_rms    /= emcal_rms_esum;
          emcal_rms     = sqrt( emcal_rms );
        }
      else
        {
          emcal_radius = -1;
          emcal_rms = -1;
        }

      /* Search for cone angle that contains 90% of jet energy */
      for(int r_i = 1; r_i<n_steps+1; r_i++){
        float e_tower_sum = 0;

        /* Loop over all tower (and geometry) collections */
        for (type_map_cdata::iterator iter_calo = map_towers->begin();
             iter_calo != map_towers->end();
             ++iter_calo)
          {
            /* define tower iterator */
            RawTowerContainer::ConstRange begin_end = ((iter_calo->second).first)->getTowers();
            RawTowerContainer::ConstIterator rtiter;

            if (e_tower_sum >= 0.9*jet_e) break;

            for (rtiter = begin_end.first; rtiter !=  begin_end.second; ++rtiter)
              {
                RawTower *tower = rtiter->second;
                float tower_energy = tower->get_energy();

                /* check if tower is above minimum tower energy required */
                if ( tower_energy < tower_emin )
                  continue;

                RawTowerGeom * tower_geom = ((iter_calo->second).second)->get_tower_geometry(tower -> get_key());
                float tower_eta = tower_geom->get_eta();
                float tower_phi = tower_geom->get_phi();

                float delta_R = CalculateDeltaR( tower_eta , tower_phi, jet_eta, jet_phi );

                if(delta_R < r_i*delta_R_cutoff_r5/n_steps) {
                  e_tower_sum = e_tower_sum + tower_energy;
                  r90 = r_i*delta_R_cutoff_r5/n_steps;
                }
              }

            if (e_tower_sum >= 0.9*jet_e) break;
          }
      }

      /* set tau candidate properties */
      (iter->second)->set_property( PidCandidate::jetshape_econe_r01, er1 );
      (iter->second)->set_property( PidCandidate::jetshape_econe_r02, er2 );
      (iter->second)->set_property( PidCandidate::jetshape_econe_r03, er3 );
      (iter->second)->set_property( PidCandidate::jetshape_econe_r04, er4 );
      (iter->second)->set_property( PidCandidate::jetshape_econe_r05, er5 );
      (iter->second)->set_property( PidCandidate::jetshape_r90, r90 );
      (iter->second)->set_property( PidCandidate::jetshape_rms, rms );
      (iter->second)->set_property( PidCandidate::jetshape_radius, radius );
      (iter->second)->set_property( PidCandidate::jetshape_emcal_econe_r01, emcal_er1 );
      (iter->second)->set_property( PidCandidate::jetshape_emcal_econe_r02, emcal_er2 );
      (iter->second)->set_property( PidCandidate::jetshape_emcal_econe_r03, emcal_er3 );
      (iter->second)->set_property( PidCandidate::jetshape_emcal_econe_r04, emcal_er4 );
      (iter->second)->set_property( PidCandidate::jetshape_emcal_econe_r05, emcal_er5 );
      (iter->second)->set_property( PidCandidate::jetshape_emcal_r90, emcal_r90 );
      (iter->second)->set_property( PidCandidate::jetshape_emcal_rms, emcal_rms );
      (iter->second)->set_property( PidCandidate::jetshape_emcal_radius, emcal_radius );
    }

  return 0;
}
int
LeptoquarksReco::AddGlobalEventInformation( type_map_tcan& tauCandidateMap, type_map_cdata* map_towers )
{
  /* missing transverse momentum */
  //float pt_miss = 0;

  /* direction of missing transverse momentum */
  //float pt_miss_phi = 0;

  /* Missing transverse energy, transverse energy direction, and Energy sums, x and y components separately */
  float Et_miss = 0;
  float Et_miss_phi = 0;
  float Ex_sum = 0;
  float Ey_sum = 0;

  /* energy threshold for considering tower */
  float tower_emin = 0.0;

  /* Loop over all tower (and geometry) collections */
  for (type_map_cdata::iterator iter_calo = map_towers->begin();
       iter_calo != map_towers->end();
       ++iter_calo)
    {

      /* define tower iterator */
      RawTowerContainer::ConstRange begin_end = ((iter_calo->second).first)->getTowers();
      RawTowerContainer::ConstIterator rtiter;

      /* loop over all tower in CEMC calorimeter */
      for (rtiter = begin_end.first; rtiter !=  begin_end.second; ++rtiter)
        {
          /* get tower energy */
          RawTower *tower = rtiter->second;
          float tower_energy = tower->get_energy();

          /* check if tower above energy treshold */
          if ( tower_energy < tower_emin )
	  continue;

          /* get eta and phi of tower and check angle delta_R w.r.t. jet axis */
          RawTowerGeom * tower_geom = ((iter_calo->second).second)->get_tower_geometry(tower -> get_key());
          float tower_eta = tower_geom->get_eta();
          float tower_phi = tower_geom->get_phi();

          /* from https://en.wikipedia.org/wiki/Pseudorapidity:
             p_x = p_T * cos( phi )
             p_y = p_T * sin( phi )
             p_z = p_T * sinh( eta )
             |p| = p_T * cosh( eta )
          */

          /* calculate 'transverse' tower energy */
          float tower_energy_t = tower_energy / cosh( tower_eta );

          /* add energy components of this tower to total energy components */
          Ex_sum += tower_energy_t * cos( tower_phi );
          Ey_sum += tower_energy_t * sin( tower_phi );
        }
      }
  
  /* calculate Et_miss and phi angle*/
  Et_miss = sqrt( Ex_sum * Ex_sum + Ey_sum * Ey_sum );
  Et_miss_phi = atan2( Ey_sum , Ex_sum );

  /* Loop over tau candidates and find tau jet*/
  PidCandidate* the_tau = NULL;
  for (type_map_tcan::iterator iter = tauCandidateMap.begin();
       iter != tauCandidateMap.end();
       ++iter)
    {
      if ( ( iter->second)->get_property_int( PidCandidate::evtgen_pid ) == 15 )
        the_tau = iter->second;
    }
  
  /* update event information tree variables */
  /* @TODO make this better protected against errors- if 'find' returns NULL pointer,
     this will lead to a SEGMENTATION FAULT */
  ( _map_event_branches.find( "Et_miss" ) )->second = Et_miss;
  ( _map_event_branches.find( "Et_miss_phi" ) )->second = Et_miss_phi;

  // If tau is found, write variables //
  if ( the_tau )
    {
      ( _map_event_branches.find( "reco_tau_found" ) )->second = 1;
      ( _map_event_branches.find( "reco_tau_is_tau" ) )->second =
        the_tau->get_property_int( PidCandidate::evtgen_pid );
      ( _map_event_branches.find( "reco_tau_eta" ) )->second =
        the_tau->get_property_float( PidCandidate::jet_eta );
      ( _map_event_branches.find( "reco_tau_phi" ) )->second =
        the_tau->get_property_float( PidCandidate::jet_phi );
      ( _map_event_branches.find( "reco_tau_ptotal" ) )->second =
        the_tau->get_property_float( PidCandidate::jet_ptotal );
    }
  else
    {
      ( _map_event_branches.find( "reco_tau_found" ) )->second = 0;
      ( _map_event_branches.find( "reco_tau_is_tau" ) )->second = NAN;
      ( _map_event_branches.find( "reco_tau_eta" ) )->second = NAN;
      ( _map_event_branches.find( "reco_tau_phi" ) )->second = NAN;
      ( _map_event_branches.find( "reco_tau_ptotal" ) )->second = NAN;
    }

  return 0;
}
Beispiel #12
0
int
Proto2ShowerCalib::process_event(PHCompositeNode *topNode)
{

  if (verbosity > 2)
    cout << "Proto2ShowerCalib::process_event() entered" << endl;

  // init eval objects
  _eval_run.reset();
  _eval_3x3_raw.reset();
  _eval_5x5_raw.reset();
  _eval_3x3_prod.reset();
  _eval_5x5_prod.reset();
  _eval_3x3_temp.reset();
  _eval_5x5_temp.reset();
  _eval_3x3_recalib.reset();
  _eval_5x5_recalib.reset();

  Fun4AllHistoManager *hm = get_HistoManager();
  assert(hm);

  if (not _is_sim)
    {
      PdbParameterMap *info = findNode::getClass<PdbParameterMap>(topNode,
          "RUN_INFO");

      assert(info);

      PHG4Parameters run_info_copy("RunInfo");
      run_info_copy.FillFrom(info);

      _eval_run.beam_mom = run_info_copy.get_double_param("beam_MTNRG_GeV");

      TH1F * hBeam_Mom = dynamic_cast<TH1F *>(hm->getHisto("hBeam_Mom"));
      assert(hBeam_Mom);

      hBeam_Mom->Fill(_eval_run.beam_mom);
    }

  EventHeader* eventheader = findNode::getClass<EventHeader>(topNode,
      "EventHeader");
  if (not _is_sim)
    {
      assert(eventheader);

      _eval_run.run = eventheader->get_RunNumber();
      if (verbosity > 4)
        cout << __PRETTY_FUNCTION__ << _eval_run.run << endl;

      _eval_run.event = eventheader->get_EvtSequence();
    }

  if (_is_sim)
    {

      PHG4TruthInfoContainer* truthInfoList = findNode::getClass<
          PHG4TruthInfoContainer>(topNode, "G4TruthInfo");

      assert(truthInfoList);

      _eval_run.run = -1;

      const PHG4Particle * p = truthInfoList->GetPrimaryParticleRange().first->second;
      assert(p);

      const PHG4VtxPoint * v = truthInfoList->GetVtx(p->get_vtx_id());
      assert(v);

      _eval_run.beam_mom = sqrt(
          p->get_px() * p->get_px() + p->get_py() * p->get_py()
              + p->get_pz() * p->get_pz());
      _eval_run.truth_y = v->get_y();
      _eval_run.truth_z = v->get_z();

    }

  // normalization
  TH1F * hNormalization = dynamic_cast<TH1F *>(hm->getHisto("hNormalization"));
  assert(hNormalization);

  hNormalization->Fill("ALL", 1);

  RawTowerContainer* TOWER_RAW_CEMC = findNode::getClass<RawTowerContainer>(
      topNode, _is_sim ? "TOWER_RAW_LG_CEMC" : "TOWER_RAW_CEMC");
  assert(TOWER_RAW_CEMC);
  RawTowerContainer* TOWER_CALIB_CEMC = findNode::getClass<RawTowerContainer>(
      topNode, _is_sim ? "TOWER_CALIB_LG_CEMC" : "TOWER_CALIB_CEMC");
  assert(TOWER_CALIB_CEMC);

  // other nodes
  RawTowerContainer* TOWER_CALIB_TRIGGER_VETO = findNode::getClass<
      RawTowerContainer>(topNode, "TOWER_CALIB_TRIGGER_VETO");
  if (not _is_sim)
    {
      assert(TOWER_CALIB_TRIGGER_VETO);
    }

  RawTowerContainer* TOWER_CALIB_HODO_HORIZONTAL = findNode::getClass<
      RawTowerContainer>(topNode, "TOWER_CALIB_HODO_HORIZONTAL");
  if (not _is_sim)
    {
      assert(TOWER_CALIB_HODO_HORIZONTAL);
    }
  RawTowerContainer* TOWER_CALIB_HODO_VERTICAL = findNode::getClass<
      RawTowerContainer>(topNode, "TOWER_CALIB_HODO_VERTICAL");
  if (not _is_sim)
    {
      assert(TOWER_CALIB_HODO_VERTICAL);
    }

  RawTowerContainer* TOWER_TEMPERATURE_EMCAL = findNode::getClass<
      RawTowerContainer>(topNode, "TOWER_TEMPERATURE_EMCAL");
  if (not _is_sim)
    {
      assert(TOWER_TEMPERATURE_EMCAL);
    }

  RawTowerContainer* TOWER_CALIB_C1 = findNode::getClass<RawTowerContainer>(
      topNode, "TOWER_CALIB_C1");
  if (not _is_sim)
    {
      assert(TOWER_CALIB_C1);
    }
  RawTowerContainer* TOWER_CALIB_C2 = findNode::getClass<RawTowerContainer>(
      topNode, "TOWER_CALIB_C2");
  if (not _is_sim)
    {
      assert(TOWER_CALIB_C2);
    }

  // Cherenkov
  bool cherekov_e = false;
  if (not _is_sim)
    {
      RawTower * t_c2_in = NULL;
      RawTower * t_c2_out = NULL;

      assert(eventheader);
      if (eventheader->get_RunNumber() >= 2105)
        {
          t_c2_in = TOWER_CALIB_C2->getTower(10);
          t_c2_out = TOWER_CALIB_C2->getTower(11);
        }
      else
        {
          t_c2_in = TOWER_CALIB_C2->getTower(0);
          t_c2_out = TOWER_CALIB_C2->getTower(1);
        }
      assert(t_c2_in);
      assert(t_c2_out);

      const double c2_in = t_c2_in->get_energy();
      const double c2_out = t_c2_out->get_energy();
      const double c1 = TOWER_CALIB_C1->getTower(0)->get_energy();

      _eval_run.C2_sum = c2_in + c2_out;
      cherekov_e = (_eval_run.C2_sum) > 100;
      hNormalization->Fill("C2-e", cherekov_e);

      TH2F * hCheck_Cherenkov = dynamic_cast<TH2F *>(hm->getHisto(
          "hCheck_Cherenkov"));
      assert(hCheck_Cherenkov);
      hCheck_Cherenkov->Fill(c1, "C1", 1);
      hCheck_Cherenkov->Fill(c2_in, "C2 in", 1);
      hCheck_Cherenkov->Fill(c2_out, "C2 out", 1);
      hCheck_Cherenkov->Fill(c2_in + c2_out, "C2 sum", 1);
    }

  // veto
  TH1F * hCheck_Veto = dynamic_cast<TH1F *>(hm->getHisto("hCheck_Veto"));
  assert(hCheck_Veto);
  bool trigger_veto_pass = true;
  if (not _is_sim)
    {
      auto range = TOWER_CALIB_TRIGGER_VETO->getTowers();
      for (auto it = range.first; it != range.second; ++it)
        {
          RawTower* tower = it->second;
          assert(tower);

          hCheck_Veto->Fill(tower->get_energy());

          if (abs(tower->get_energy()) > 15)
            trigger_veto_pass = false;
        }
    }
  hNormalization->Fill("trigger_veto_pass", trigger_veto_pass);
  _eval_run.trigger_veto_pass = trigger_veto_pass;

  // hodoscope
  TH1F * hCheck_Hodo_H = dynamic_cast<TH1F *>(hm->getHisto("hCheck_Hodo_H"));
  assert(hCheck_Hodo_H);
  int hodo_h_count = 0;
  if (not _is_sim)
    {
      auto range = TOWER_CALIB_HODO_HORIZONTAL->getTowers();
      for (auto it = range.first; it != range.second; ++it)
        {
          RawTower* tower = it->second;
          assert(tower);

          hCheck_Hodo_H->Fill(tower->get_energy());

          if (abs(tower->get_energy()) > 30)
            {
              hodo_h_count++;
              _eval_run.hodo_h = tower->get_id();
            }
        }
    }
  const bool valid_hodo_h = hodo_h_count == 1;
  hNormalization->Fill("valid_hodo_h", valid_hodo_h);
  _eval_run.valid_hodo_h = valid_hodo_h;

  TH1F * hCheck_Hodo_V = dynamic_cast<TH1F *>(hm->getHisto("hCheck_Hodo_V"));
  assert(hCheck_Hodo_V);
  int hodo_v_count = 0;
  if (not _is_sim)
    {
      auto range = TOWER_CALIB_HODO_VERTICAL->getTowers();
      for (auto it = range.first; it != range.second; ++it)
        {
          RawTower* tower = it->second;
          assert(tower);

          hCheck_Hodo_V->Fill(tower->get_energy());

          if (abs(tower->get_energy()) > 30)
            {
              hodo_v_count++;
              _eval_run.hodo_v = tower->get_id();
            }
        }
    }
  const bool valid_hodo_v = hodo_v_count == 1;
  _eval_run.valid_hodo_v = valid_hodo_v;
  hNormalization->Fill("valid_hodo_v", valid_hodo_v);

  const bool good_e = (valid_hodo_v and valid_hodo_h and cherekov_e
      and trigger_veto_pass) and (not _is_sim);
  hNormalization->Fill("good_e", good_e);

  // simple clustering
  pair<int, int> max_3x3 = find_max(TOWER_CALIB_CEMC, 3);
  pair<int, int> max_5x5 = find_max(TOWER_CALIB_CEMC, 5);

  _eval_3x3_raw.max_col = max_3x3.first;
  _eval_3x3_raw.max_row = max_3x3.second;
  _eval_3x3_prod.max_col = max_3x3.first;
  _eval_3x3_prod.max_row = max_3x3.second;
  _eval_3x3_temp.max_col = max_3x3.first;
  _eval_3x3_temp.max_row = max_3x3.second;
  _eval_3x3_recalib.max_col = max_3x3.first;
  _eval_3x3_recalib.max_row = max_3x3.second;

  _eval_5x5_raw.max_col = max_5x5.first;
  _eval_5x5_raw.max_row = max_5x5.second;
  _eval_5x5_prod.max_col = max_5x5.first;
  _eval_5x5_prod.max_row = max_5x5.second;
  _eval_5x5_temp.max_col = max_5x5.first;
  _eval_5x5_temp.max_row = max_5x5.second;
  _eval_5x5_recalib.max_col = max_5x5.first;
  _eval_5x5_recalib.max_row = max_5x5.second;

  // tower
  bool good_temp = true;
  double sum_energy_calib = 0;
  double sum_energy_T = 0;
  TH1F * hTemperature = dynamic_cast<TH1F *>(hm->getHisto("hTemperature"));
  assert(hTemperature);

  stringstream sdata;

  if (good_e)
    sdata << abs(_eval_run.beam_mom) << "\t";

  // tower temperature and recalibration
    {
      auto range = TOWER_CALIB_CEMC->getTowers();
      for (auto it = range.first; it != range.second; ++it)
        {

          RawTowerDefs::keytype key = it->first;
          RawTower* tower = it->second;
          assert(tower);

          const int col = tower->get_bineta();
          const int row = tower->get_binphi();

          if (col < 0 or col >= 8)
            continue;
          if (row < 0 or row >= 8)
            continue;

          const double energy_calib = tower->get_energy();
          sum_energy_calib += energy_calib;

          RawTower* tower_raw = TOWER_RAW_CEMC->getTower(key);
          assert(tower_raw);

          double energy_T = 0;
          if (not _is_sim)
            {
              RawTower_Temperature * temp_t =
                  dynamic_cast<RawTower_Temperature *>(TOWER_TEMPERATURE_EMCAL->getTower(
                      tower->get_row(), tower->get_column())); // note swap of col/row in temperature storage
              assert(temp_t);

              const double T = temp_t->get_temperature_from_time(
                  eventheader->get_TimeStamp());
              hTemperature->Fill(T);

              if (T < 25 or T > 35)
                good_temp = false;

              energy_T = TemperatureCorrection::Apply(energy_calib, T);
            }

          // recalibration
          assert(
              _recalib_const.find(make_pair(col, row)) != _recalib_const.end());
          const double energy_recalib = energy_T
              * _recalib_const[make_pair(col, row)];

          // energy sums
          sum_energy_T += energy_T;

          // calibration file
//          sdata << tower->get_energy() << "\t";
          // calibration file - only output 5x5 towers
          if (col >= max_5x5.first - 2 and col <= max_5x5.first + 2
              and row >= max_5x5.second - 2 and row <= max_5x5.second + 2)
            {
              sdata << tower->get_energy() << "\t";
            }
          else
            {
              sdata << 0 << "\t";
            }

          // cluster 3x3
          if (col >= max_3x3.first - 1 and col <= max_3x3.first + 1)
            if (row >= max_3x3.second - 1 and row <= max_3x3.second + 1)
              {
                // in cluster

                _eval_3x3_raw.average_col += abs(tower_raw->get_energy()) * col;
                _eval_3x3_raw.average_row += abs(tower_raw->get_energy()) * row;
                _eval_3x3_raw.sum_E += abs(tower_raw->get_energy());

                _eval_3x3_prod.average_col += energy_calib * col;
                _eval_3x3_prod.average_row += energy_calib * row;
                _eval_3x3_prod.sum_E += energy_calib;

                _eval_3x3_temp.average_col += energy_T * col;
                _eval_3x3_temp.average_row += energy_T * row;
                _eval_3x3_temp.sum_E += energy_T;

                _eval_3x3_recalib.average_col += energy_recalib * col;
                _eval_3x3_recalib.average_row += energy_recalib * row;
                _eval_3x3_recalib.sum_E += energy_recalib;
              }

          // cluster 5x5
          if (col >= max_5x5.first - 2 and col <= max_5x5.first + 2)
            if (row >= max_5x5.second - 2 and row <= max_5x5.second + 2)
              {
                // in cluster

                _eval_5x5_raw.average_col += abs(tower_raw->get_energy()) * col;
                _eval_5x5_raw.average_row += abs(tower_raw->get_energy()) * row;
                _eval_5x5_raw.sum_E += abs(tower_raw->get_energy());

                _eval_5x5_prod.average_col += energy_calib * col;
                _eval_5x5_prod.average_row += energy_calib * row;
                _eval_5x5_prod.sum_E += energy_calib;

                _eval_5x5_temp.average_col += energy_T * col;
                _eval_5x5_temp.average_row += energy_T * row;
                _eval_5x5_temp.sum_E += energy_T;

                _eval_5x5_recalib.average_col += energy_recalib * col;
                _eval_5x5_recalib.average_row += energy_recalib * row;
                _eval_5x5_recalib.sum_E += energy_recalib;
              }
        }
    }

  _eval_3x3_raw.reweight_clus_pol();
  _eval_5x5_raw.reweight_clus_pol();
  _eval_3x3_prod.reweight_clus_pol();
  _eval_5x5_prod.reweight_clus_pol();
  _eval_3x3_temp.reweight_clus_pol();
  _eval_5x5_temp.reweight_clus_pol();
  _eval_3x3_recalib.reweight_clus_pol();
  _eval_5x5_recalib.reweight_clus_pol();

  const double EoP = sum_energy_T / abs(_eval_run.beam_mom);
  hNormalization->Fill("good_temp", good_temp);

  bool good_data = good_e and good_temp;
  hNormalization->Fill("good_data", good_data);

  _eval_run.good_temp = good_temp;
  _eval_run.good_e = good_e;
  _eval_run.good_data = good_data;
  _eval_run.sum_energy_T = sum_energy_T;
  _eval_run.EoP = EoP;

  // E/p
  if (good_data)
    {
      if (verbosity >= 3)
        cout << __PRETTY_FUNCTION__ << " sum_energy_calib = "
            << sum_energy_calib << " sum_energy_T = " << sum_energy_T
            << " _eval_run.beam_mom = " << _eval_run.beam_mom << endl;

      TH2F * hEoP = dynamic_cast<TH2F *>(hm->getHisto("hEoP"));
      assert(hEoP);

      hEoP->Fill(EoP, abs(_eval_run.beam_mom));
    }

  // calibration file
  if (good_data and abs(_eval_run.beam_mom) >= 4
      and abs(_eval_run.beam_mom) <= 8)
    {
      assert(fdata.is_open());

      fdata << sdata.str();

      fdata << endl;
    }

  TTree * T = dynamic_cast<TTree *>(hm->getHisto("T"));
  assert(T);
  T->Fill();

  return Fun4AllReturnCodes::EVENT_OK;
}
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_Tower(PHCompositeNode *topNode)
{
  const string detector(_calo_name);

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

  Fun4AllHistoManager *hm = QAHistManagerDef::getHistoManager();
  assert(hm);
  TH1D* h_norm = dynamic_cast<TH1D*>(hm->getHisto(
      get_histo_prefix() + "_Normalization"));
  assert(h_norm);

  string towernodename = "TOWER_CALIB_" + detector;
  // Grab the towers
  RawTowerContainer* towers = findNode::getClass<RawTowerContainer>(topNode,
      towernodename.c_str());
  if (!towers)
    {
      std::cout << PHWHERE << ": Could not find node " << towernodename.c_str()
          << std::endl;
      return Fun4AllReturnCodes::ABORTRUN;
    }
  string towergeomnodename = "TOWERGEOM_" + detector;
  RawTowerGeomContainer *towergeom = findNode::getClass<RawTowerGeomContainer>(
      topNode, towergeomnodename.c_str());
  if (!towergeom)
    {
      cout << PHWHERE << ": Could not find node " << towergeomnodename.c_str()
          << endl;
      return Fun4AllReturnCodes::ABORTRUN;
    }

  static const int max_size = 5;
  map<int, string> size_label;
  size_label[1] = "1x1";
  size_label[2] = "2x2";
  size_label[3] = "3x3";
  size_label[4] = "4x4";
  size_label[5] = "5x5";
  map<int, double> max_energy;
  map<int, TH1F*> energy_hist_list;
  map<int, TH1F*> max_energy_hist_list;

  for (int size = 1; size <= max_size; ++size)
    {
      max_energy[size] = 0;


      TH1F* h = dynamic_cast<TH1F*>(hm->getHisto(
          get_histo_prefix() + "_Tower_" + size_label[size]));
      assert(h);
      energy_hist_list[size] = h;
      h = dynamic_cast<TH1F*>(hm->getHisto(
          get_histo_prefix() + "_Tower_" + size_label[size] + "_max"));
      assert(h);
      max_energy_hist_list[size] = h;

    }

  h_norm->Fill("Tower", towergeom->size()); // total tower count
  h_norm->Fill("Tower Hit", towers->size());

  for (int binphi = 0; binphi < towergeom->get_phibins(); ++binphi)
    {
      for (int bineta = 0; bineta < towergeom->get_etabins(); ++bineta)
        {
          for (int size = 1; size <= max_size; ++size)
            {

              // for 2x2 and 4x4 use slide-2 window as implemented in DAQ
              if ((size == 2 or size == 4)
                  and ((binphi % 2 != 0) and (bineta % 2 != 0)))
                continue;

              double energy = 0;

              // sliding window made from 2x2 sums
              for (int iphi = binphi; iphi < binphi + size; ++iphi)
                {
                  for (int ieta = bineta; ieta < bineta + size; ++ieta)
                    {
                      if (ieta > towergeom->get_etabins())
                        continue;

                      // wrap around
                      int wrapphi = iphi;
                      assert(wrapphi >= 0);
                      if (wrapphi >= towergeom->get_phibins())
                        {
                          wrapphi = wrapphi - towergeom->get_phibins();
                        }

                      RawTower* tower = towers->getTower(ieta, wrapphi);

                      if (tower)
                        {
                          const double e_intput = tower->get_energy();

                          energy += e_intput;
                        }
                    }
                }

              energy_hist_list[size]->Fill(energy == 0 ? 9.1e-4 : energy); // trick to fill 0 energy tower to the first bin

              if (energy > max_energy[size])
                max_energy[size] = energy;

            } //          for (int size = 1; size <= 4; ++size)
        }
    }

  for (int size = 1; size <= max_size; ++size)
    {
      max_energy_hist_list[size]->Fill(max_energy[size]);
    }
  return Fun4AllReturnCodes::EVENT_OK;
}