Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392
#include <iostream>
#include <fstream>
#include <algorithm>
#include <numeric>

#include "TString.h"
#include "FWCore/MessageLogger/interface/MessageLogger.h"
#include "Calibration/HcalCalibAlgos/interface/hcalCalibUtils.h"

//#include "Calibration/HcalCalibAlgos/plugins/CommonUsefulStuff.h"
#include "Calibration/HcalCalibAlgos/interface/CommonUsefulStuff.h"
#include "DataFormats/DetId/interface/DetId.h"
#include "Geometry/HcalTowerAlgo/interface/HcalGeometry.h"

void sumDepths(std::vector<TCell>& selectCells) {
  // Assignes teh sum of the energy in cells with the same iEta, iPhi to the cell with depth=1.
  // All cells with depth>1 are removed form the container. If
  // the cell at depth=1 is not present: create it and follow the procedure.

  if (selectCells.empty())
    return;

  std::vector<TCell> selectCellsDepth1;
  std::vector<TCell> selectCellsHighDepth;

  //
  // NB: Here we add depth 3 for iEta==16 in *HE* to the value in the barrel
  // this approach is reflected in several of the following loops: make sure
  // to check when making changes.
  //
  // In some documents it is described as having depth 1, the mapping in CMSSW uses depth 3.

  for (std::vector<TCell>::iterator i_it = selectCells.begin(); i_it != selectCells.end(); ++i_it) {
    if (HcalDetId(i_it->id()).depth() == 1) {
      selectCellsDepth1.push_back(*i_it);
    } else {
      selectCellsHighDepth.push_back(*i_it);
    }
  }

  // case where depth 1 has zero energy, but higher depths with same (iEta, iPhi) have energy.
  // For iEta<15 there is one depth -> selectCellsHighDepth is empty and we do not get in the loop.
  for (std::vector<TCell>::iterator i_it2 = selectCellsHighDepth.begin(); i_it2 != selectCellsHighDepth.end();
       ++i_it2) {
    // protect against corrupt data
    if (HcalDetId(i_it2->id()).ietaAbs() < 15 && HcalDetId(i_it2->id()).depth() > 1) {
      edm::LogWarning("HcalCalib") << "ERROR!!! there are no HB cells with depth>1 for iEta<15!\n"
                                   << "Check the input data...\nHCalDetId: " << HcalDetId(i_it2->id());
      return;
    }

    bool foundDepthOne = false;
    for (std::vector<TCell>::iterator i_it = selectCellsDepth1.begin(); i_it != selectCellsDepth1.end(); ++i_it) {
      if (HcalDetId(i_it->id()).ieta() == HcalDetId(i_it2->id()).ieta() &&
          HcalDetId(i_it->id()).iphi() == HcalDetId(i_it2->id()).iphi())
        foundDepthOne = true;
      continue;
    }
    if (!foundDepthOne) {  // create entry for depth 1 with 0 energy

      UInt_t newId;
      if (abs(HcalDetId(i_it2->id()).ieta()) == 16)
        newId = HcalDetId(HcalBarrel, HcalDetId(i_it2->id()).ieta(), HcalDetId(i_it2->id()).iphi(), 1);
      else
        newId =
            HcalDetId(HcalDetId(i_it2->id()).subdet(), HcalDetId(i_it2->id()).ieta(), HcalDetId(i_it2->id()).iphi(), 1);

      selectCellsDepth1.push_back(TCell(newId, 0.0));
    }
  }

  for (std::vector<TCell>::iterator i_it = selectCellsDepth1.begin(); i_it != selectCellsDepth1.end(); ++i_it) {
    for (std::vector<TCell>::iterator i_it2 = selectCellsHighDepth.begin(); i_it2 != selectCellsHighDepth.end();
         ++i_it2) {
      if (HcalDetId(i_it->id()).ieta() == HcalDetId(i_it2->id()).ieta() &&
          HcalDetId(i_it->id()).iphi() == HcalDetId(i_it2->id()).iphi()) {
        i_it->SetE(i_it->e() + i_it2->e());
        i_it2->SetE(0.0);  // paranoid, aren't we...
      }
    }
  }

  // replace the original vectors with the new ones
  selectCells = selectCellsDepth1;

  return;
}

void combinePhi(std::vector<TCell>& selectCells) {
  // Map: NxN -> N cluster
  // Comine the targetE of cells with the same iEta

  if (selectCells.empty())
    return;

  // new container for the TCells
  // dummy cell id created with iEta; iPhi=1; depth
  // if combinePhi() is run after combining depths, depth=1
  std::vector<TCell> combinedCells;

  std::map<UInt_t, std::vector<Float_t> > etaSliceE;  // keyed by id of cell with iEta and **iPhi=1**

  // map the cells to the eta ring
  std::vector<TCell>::iterator i_it = selectCells.begin();
  for (; i_it != selectCells.end(); ++i_it) {
    DetId id = HcalDetId(i_it->id());
    UInt_t thisKey = HcalDetId(HcalDetId(id).subdet(), HcalDetId(id).ieta(), 1, HcalDetId(id).depth());
    etaSliceE[thisKey].push_back(i_it->e());
  }

  std::map<UInt_t, std::vector<Float_t> >::iterator m_it = etaSliceE.begin();
  for (; m_it != etaSliceE.end(); ++m_it) {
    combinedCells.push_back(TCell(m_it->first, accumulate(m_it->second.begin(), m_it->second.end(), 0.0)));
  }

  // replace the original TCell vector with the new one
  selectCells = combinedCells;
}

void combinePhi(std::vector<TCell>& selectCells, std::vector<TCell>& combinedCells) {
  // Map: NxN -> N cluster
  // Comine the targetE of cells with the same iEta

  if (selectCells.empty())
    return;

  std::map<UInt_t, std::vector<Float_t> > etaSliceE;  // keyed by id of cell with iEta and **iPhi=1**

  // map the cells to the eta ring
  std::vector<TCell>::iterator i_it = selectCells.begin();
  for (; i_it != selectCells.end(); ++i_it) {
    DetId id = HcalDetId(i_it->id());
    UInt_t thisKey = HcalDetId(HcalDetId(id).subdet(), HcalDetId(id).ieta(), 1, HcalDetId(id).depth());
    etaSliceE[thisKey].push_back(i_it->e());
  }

  std::map<UInt_t, std::vector<Float_t> >::iterator m_it = etaSliceE.begin();
  for (; m_it != etaSliceE.end(); ++m_it) {
    combinedCells.push_back(TCell(m_it->first, accumulate(m_it->second.begin(), m_it->second.end(), 0.0)));
  }
}

void getIEtaIPhiForHighestE(std::vector<TCell>& selectCells, Int_t& iEtaMostE, UInt_t& iPhiMostE) {
  std::vector<TCell> summedDepthsCells = selectCells;

  sumDepths(summedDepthsCells);
  std::vector<TCell>::iterator highCell = summedDepthsCells.begin();

  // sum depths locally to get highest energy tower

  Float_t highE = -999;

  for (std::vector<TCell>::iterator it = summedDepthsCells.begin(); it != summedDepthsCells.end(); ++it) {
    if (highE < it->e()) {
      highCell = it;
      highE = it->e();
    }
  }

  iEtaMostE = HcalDetId(highCell->id()).ieta();
  iPhiMostE = HcalDetId(highCell->id()).iphi();

  return;
}

//
// Remove RecHits outside the 3x3 cluster and replace the  vector that will
// be used in the minimization. Acts on "event" level.
// This can not be done for iEta>20 due to segmentation => in principle the result should be restricted
// to iEta<20. Attempted to minimize affect at the boundary without a sharp jump.

void filterCells3x3(std::vector<TCell>& selectCells, Int_t iEtaMaxE, UInt_t iPhiMaxE) {
  std::vector<TCell> filteredCells;

  Int_t dEta, dPhi;

  for (std::vector<TCell>::iterator it = selectCells.begin(); it != selectCells.end(); ++it) {
    Bool_t passDEta = false;
    Bool_t passDPhi = false;

    dEta = HcalDetId(it->id()).ieta() - iEtaMaxE;
    dPhi = HcalDetId(it->id()).iphi() - iPhiMaxE;

    if (dPhi > 36)
      dPhi -= 72;
    if (dPhi < -36)
      dPhi += 72;

    if (abs(dEta) <= 1 || (iEtaMaxE * HcalDetId(it->id()).ieta() == -1))
      passDEta = true;

    if (abs(iEtaMaxE) <= 20) {
      if (abs(HcalDetId(it->id()).ieta()) <= 20) {
        if (abs(dPhi) <= 1)
          passDPhi = true;
      } else {
        // iPhi is labelled by odd numbers
        if (iPhiMaxE % 2 == 0) {
          if (abs(dPhi) <= 1)
            passDPhi = true;
        } else {
          if (dPhi == -2 || dPhi == 0)
            passDPhi = true;
        }
      }

    }  // if hottest cell with iEta<=20

    else {
      if (abs(HcalDetId(it->id()).ieta()) <= 20) {
        if (abs(dPhi) <= 1 || dPhi == 2)
          passDPhi = true;
      } else {
        if (abs(dPhi) <= 2)
          passDPhi = true;
      }
    }  // if hottest cell with iEta>20

    if (passDEta && passDPhi)
      filteredCells.push_back(*it);
  }

  selectCells = filteredCells;

  return;
}

//
// Remove RecHits outside the 5x5 cluster and replace the  vector that will
// be used in the minimization. Acts on "event" level
// In principle the ntuple should be produced with 5x5 already precelected
//
// Size for iEta>20 is 3x3, but the segmentation changes by x2 in phi.
// There is some bias in the selection of towers near the boundary

void filterCells5x5(std::vector<TCell>& selectCells, Int_t iEtaMaxE, UInt_t iPhiMaxE) {
  std::vector<TCell> filteredCells;

  Int_t dEta, dPhi;

  for (std::vector<TCell>::iterator it = selectCells.begin(); it != selectCells.end(); ++it) {
    dEta = HcalDetId(it->id()).ieta() - iEtaMaxE;
    dPhi = HcalDetId(it->id()).iphi() - iPhiMaxE;

    if (dPhi > 36)
      dPhi -= 72;
    if (dPhi < -36)
      dPhi += 72;

    bool passDPhi = (abs(dPhi) < 3);

    bool passDEta = (abs(dEta) < 3 || (iEtaMaxE * HcalDetId(it->id()).ieta() == -2));
    // includes  +/- eta boundary

    if (passDPhi && passDEta)
      filteredCells.push_back(*it);
  }

  selectCells = filteredCells;

  return;
}

// this is for the problematic layer near the HB/HE boundary
// sum depths 1,2 in towers 15,16

void sumSmallDepths(std::vector<TCell>& selectCells) {
  if (selectCells.empty())
    return;

  std::vector<TCell> newCells;          // holds unaffected cells to which the modified ones are added
  std::vector<TCell> manipulatedCells;  // the ones that are combined

  for (std::vector<TCell>::iterator i_it = selectCells.begin(); i_it != selectCells.end(); ++i_it) {
    if ((HcalDetId(i_it->id()).ietaAbs() == 15 && HcalDetId(i_it->id()).depth() <= 2) ||
        (HcalDetId(i_it->id()).ietaAbs() == 16 && HcalDetId(i_it->id()).depth() <= 2)) {
      manipulatedCells.push_back(*i_it);
    } else {
      newCells.push_back(*i_it);
    }
  }

  // if the list is empty there is nothing to manipulate
  // leave the original vector unchanged

  if (manipulatedCells.empty()) {
    newCells.clear();
    return;
  }

  // See what cells are needed to hold the combined information:
  // Make holders for depth=1 for each (iEta,iPhi)
  // if a cell with these values is present in "manupulatedCells"
  std::vector<UInt_t> dummyIds;     // to keep track of kreated cells
  std::vector<TCell> createdCells;  // cells that need to be added or they exists;

  for (std::vector<TCell>::iterator i_it = manipulatedCells.begin(); i_it != manipulatedCells.end(); ++i_it) {
    UInt_t dummyId =
        HcalDetId(HcalDetId(i_it->id()).subdet(), HcalDetId(i_it->id()).ieta(), HcalDetId(i_it->id()).iphi(), 1);
    if (find(dummyIds.begin(), dummyIds.end(), dummyId) == dummyIds.end()) {
      dummyIds.push_back(dummyId);
      createdCells.push_back(TCell(dummyId, 0.0));
    }
  }

  for (std::vector<TCell>::iterator i_it = createdCells.begin(); i_it != createdCells.end(); ++i_it) {
    for (std::vector<TCell>::iterator i_it2 = manipulatedCells.begin(); i_it2 != manipulatedCells.end(); ++i_it2) {
      if (HcalDetId(i_it->id()).ieta() == HcalDetId(i_it2->id()).ieta() &&
          HcalDetId(i_it->id()).iphi() == HcalDetId(i_it2->id()).iphi() && HcalDetId(i_it2->id()).depth() <= 2) {
        i_it->SetE(i_it->e() + i_it2->e());
      }
    }
  }

  for (std::vector<TCell>::iterator i_it = createdCells.begin(); i_it != createdCells.end(); ++i_it) {
    newCells.push_back(*i_it);
  }

  // replace the original vectors with the new ones
  selectCells = newCells;

  return;
}

void filterCellsInCone(std::vector<TCell>& selectCells,
                       const GlobalPoint hitPositionHcal,
                       Float_t maxConeDist,
                       const CaloGeometry* theCaloGeometry) {
  std::vector<TCell> filteredCells;

  for (std::vector<TCell>::iterator it = selectCells.begin(); it != selectCells.end(); ++it) {
    GlobalPoint recHitPoint;
    DetId id = it->id();
    if (id.det() == DetId::Hcal) {
      recHitPoint = (static_cast<const HcalGeometry*>(theCaloGeometry->getSubdetectorGeometry(id)))->getPosition(id);
    } else {
      recHitPoint = GlobalPoint(theCaloGeometry->getPosition(id));
    }

    if (getDistInPlaneSimple(hitPositionHcal, recHitPoint) <= maxConeDist)
      filteredCells.push_back(*it);
  }

  selectCells = filteredCells;

  return;
}

// From Jim H. => keep till the code is included centrally
/*
double getDistInPlaneSimple(const GlobalPoint caloPoint, const GlobalPoint rechitPoint) {
  
  // Simplified version of getDistInPlane
  // Assume track direction is origin -> point of hcal intersection
  
  const GlobalVector caloIntersectVector(caloPoint.x(), 
					 caloPoint.y(), 
					 caloPoint.z());

  const GlobalVector caloIntersectUnitVector = caloIntersectVector.unit();
  
  const GlobalVector rechitVector(rechitPoint.x(),
				  rechitPoint.y(),
				  rechitPoint.z());

  const GlobalVector rechitUnitVector = rechitVector.unit();

  double dotprod = caloIntersectUnitVector.dot(rechitUnitVector);
  double rechitdist = caloIntersectVector.mag()/dotprod;
  
  
  const GlobalVector effectiveRechitVector = rechitdist*rechitUnitVector;
  const GlobalPoint effectiveRechitPoint(effectiveRechitVector.x(),
					 effectiveRechitVector.y(),
					 effectiveRechitVector.z());
  
  
  GlobalVector distance_vector = effectiveRechitPoint-caloPoint;
  
  if (dotprod > 0.)
    {
      return distance_vector.mag();
    }
  else
    {
      return 999999.;
    
    }

    
}
*/