CMS 3D CMS Logo

EcalHitMaker.cc
Go to the documentation of this file.
5 
6 //#include "Geometry/EcalAlgo/interface/EcalBarrelGeometry.h"
7 //#include "Geometry/EcalAlgo/interface/EcalEndcapGeometry.h"
8 //#include "Geometry/CaloGeometry/interface/CaloCellGeometry.h"
9 
21 //#include "FastSimulation/Utilities/interface/Histos.h"
22 
23 //#include "Math/GenVector/Transform3D.h"
25 
26 #include <algorithm>
27 #include <cmath>
28 
32 
34  const XYZPoint& ecalentrance,
35  const DetId& cell,
36  int onEcal,
37  unsigned size,
38  unsigned showertype,
39  const RandomEngineAndDistribution* engine)
40  : CaloHitMaker(theCalo, DetId::Ecal, ((onEcal == 1) ? EcalBarrel : EcalEndcap), onEcal, showertype),
41  EcalEntrance_(ecalentrance),
42  onEcal_(onEcal),
43  myTrack_(nullptr),
44  random(engine) {
45 #ifdef FAMOSDEBUG
46  myHistos = Histos::instance();
47 #endif
48  // myHistos->debug("Constructeur EcalHitMaker");
49  simulatePreshower_ = true;
50  X0depthoffset_ = 0.;
51  X0PS1_ = 0.;
52  X0PS2_ = 0.;
53  X0PS2EE_ = 0.;
54  X0ECAL_ = 0.;
55  X0EHGAP_ = 0.;
56  X0HCAL_ = 0.;
57  L0PS1_ = 0.;
58  L0PS2_ = 0.;
59  L0PS2EE_ = 0.;
60  L0ECAL_ = 0.;
61  L0EHGAP_ = 0.;
62  L0HCAL_ = 0.;
63  maxX0_ = 0.;
64  totalX0_ = 0;
65  totalL0_ = 0.;
68  rearleakage_ = 0.;
69  bfactor_ = 1.;
70  ncrystals_ = 0;
71 
72  doreorg_ = !showertype;
73 
75 
76  if (onEcal)
78  else
79  pivot_ = Crystal();
80  central_ = onEcal == 1;
81  ecalFirstSegment_ = -1;
82 
83  myCrystalWindowMap_ = nullptr;
84  // In some cases, a "dummy" grid, not based on a cell, can be built. The previous variables
85  // should however be initialized. In such a case onEcal=0
86  if (!onEcal)
87  return;
88 
89  // Same size in eta-phi
90  etasize_ = size;
91  phisize_ = size;
92 
93  // Build the grid
94  // The result is put in CellsWindow and is ordered by distance to the pivot
96 
97  buildGeometry();
98  // std::cout << " Geometry built " << regionOfInterest_.size() << std::endl;
99 
101 
102  // A local vector of corners
103  mycorners.resize(4);
104  corners.resize(4);
105 
106 #ifdef DEBUGGW
107  myHistos->fill("h10", EcalEntrance_.eta(), CellsWindow_.size());
108  if (onEcal == 2) {
109  myHistos->fill("h20", EcalEntrance_.perp(), CellsWindow_.size());
110  if (EcalEntrance_.perp() > 70 && EcalEntrance_.perp() < 80 && CellsWindow_.size() < 35) {
111  std::cout << " Truncated grid " << CellsWindow_.size() << " " << EcalEntrance_.perp() << std::endl;
112  std::cout << " Pivot "
113  << myCalorimeter->getEcalEndcapGeometry()->getGeometry(pivot_.getDetId())->getPosition().perp();
114  std::cout << EEDetId(pivot_.getDetId()) << std::endl;
115 
116  std::cout << " Test getClosestCell " << EcalEntrance_ << std::endl;
117  DetId testcell = myCalorimeter->getClosestCell(EcalEntrance_, true, false);
118  std::cout << " Result " << EEDetId(testcell) << std::endl;
119  std::cout << " Position " << myCalorimeter->getEcalEndcapGeometry()->getGeometry(testcell)->getPosition()
120  << std::endl;
121  }
122  }
123 
124 #endif
125 }
126 
128  if (myCrystalWindowMap_ != nullptr) {
129  delete myCrystalWindowMap_;
130  }
131 }
132 
133 bool EcalHitMaker::addHitDepth(double r, double phi, double depth) {
134  // std::cout << " Add hit depth called; Current deph is " << currentdepth_;
135  // std::cout << " Required depth is " << depth << std::endl;
137  double sp(1.);
138  r *= radiusFactor_;
139  CLHEP::Hep2Vector point(r * std::cos(phi), r * std::sin(phi));
140 
141  unsigned xtal = fastInsideCell(point, sp);
142  // if(cellid.isZero()) std::cout << " cell is Zero " << std::endl;
143  // if(xtal<1000)
144  // {
145  // std::cout << "Result " << regionOfInterest_[xtal].getX0Back() << " " ;
146  // std::cout << depth << std::endl;
147  // }
148  // myHistos->fill("h5000",depth);
149  if (xtal < 1000) {
150  // myHistos->fill("h5002",regionOfInterest_[xtal].getX0Back(),depth);
151  // myHistos->fill("h5003",ecalentrance_.eta(),maxX0_);
152  if (regionOfInterest_[xtal].getX0Back() > depth) {
153  hits_[xtal] += spotEnergy;
154  // myHistos->fill("h5005",r);
155  return true;
156  } else {
158  }
159  } else {
160  // std::cout << " Return false " << std::endl;
161  // std::cout << " Add hit depth called; Current deph is " << currentdepth_;
162  // std::cout << " Required depth is " << depth << std::endl;
163  // std::cout << " R = " << r << " " << radiusFactor_ << std::endl;
164  }
165 
167  return false;
168 }
169 
170 //bool EcalHitMaker::addHitDepth(double r,double phi,double depth)
171 //{
172 // std::map<unsigned,float>::iterator itcheck=hitMap_.find(pivot_.getDetId().rawId());
173 // if(itcheck==hitMap_.end())
174 // {
175 // hitMap_.insert(std::pair<uint32_t,float>(pivot_.getDetId().rawId(),spotEnergy));
176 // }
177 // else
178 // {
179 // itcheck->second+=spotEnergy;
180 // }
181 // return true;
182 //}
183 
184 bool EcalHitMaker::addHit(double r, double phi, unsigned layer) {
185  // std::cout <<" Addhit " << std::endl;
186  // std::cout << " Before insideCell " << std::endl;
187  double sp(1.);
188  // std::cout << " Trying to add " << r << " " << phi << " " << radiusFactor_ << std::endl;
189  r *= radiusFactor_;
190  CLHEP::Hep2Vector point(r * std::cos(phi), r * std::sin(phi));
191  // std::cout << "point " << point << std::endl;
192  // CellID cellid=insideCell(point,sp);
193  unsigned xtal = fastInsideCell(point, sp);
194  // if(cellid.isZero()) std::cout << " cell is Zero " << std::endl;
195  if (xtal < 1000) {
196  if (sp == 1.)
197  hits_[xtal] += spotEnergy;
198  else
199  hits_[xtal] += (random->flatShoot() < sp) * spotEnergy;
200  return true;
201  }
202 
204  // std::cout << " This hit ; r= " << point << " hasn't been added "<<std::endl;
205  // std::cout << " Xtal " << xtal << std::endl;
206  // for(unsigned ip=0;ip<npadsatdepth_;++ip)
207  // {
208  // std::cout << padsatdepth_[ip] << std::endl;
209  // }
210 
211  return false;
212 }
213 
214 // Temporary solution
215 //bool EcalHitMaker::addHit(double r,double phi,unsigned layer)
216 //{
217 // std::map<unsigned,float>::iterator itcheck=hitMap_.find(pivot_.getDetId().rawId());
218 // if(itcheck==hitMap_.end())
219 // {
220 // hitMap_.insert(std::pair<uint32_t,float>(pivot_.getDetId().rawId(),spotEnergy));
221 // }
222 // else
223 // {
224 // itcheck->second+=spotEnergy;
225 // }
226 // return true;
227 //}
228 
229 unsigned EcalHitMaker::fastInsideCell(const CLHEP::Hep2Vector& point, double& sp, bool debug) {
230  // debug = true;
231  bool found = false;
232  // something clever has to be implemented here
233  unsigned d1, d2;
234  convertIntegerCoordinates(point.x(), point.y(), d1, d2);
235  // std::cout << "Fastinside cell " << point.x() << " " << point.y() << " " << d1 << " "<< d2 << " " << nx_ << " " << ny_ << std::endl;
236  if (d1 >= nx_ || d2 >= ny_) {
237  // std::cout << " Not in the map " <<std::endl;
238  return 9999;
239  }
240  unsigned cell = myCrystalNumberArray_[d1][d2];
241  // We are likely to be lucky
242  // std::cout << " Got the cell " << cell << std::endl;
243  if (validPads_[cell] && padsatdepth_[cell].inside(point)) {
244  // std::cout << " We are lucky " << cell << std::endl;
245  sp = padsatdepth_[cell].survivalProbability();
246  return cell;
247  }
248 
249  // std::cout << "Starting the loop " << std::endl;
250  bool status(true);
251  const std::vector<unsigned>& localCellVector(myCrystalWindowMap_->getCrystalWindow(cell, status));
252  if (status) {
253  unsigned size = localCellVector.size();
254  // std::cout << " Starting from " << EBDetId(regionOfInterest_[cell].getDetId()) << std::endl;
255  // const std::vector<DetId>& neighbours=myCalorimeter->getNeighbours(regionOfInterest_[cell].getDetId());
256  // std::cout << " The neighbours are " << std::endl;
257  // for(unsigned ic=0;ic<neighbours.size(); ++ic)
258  // {
259  // std::cout << EBDetId(neighbours[ic]) << std::endl;
260  // }
261  // std::cout << " Done " << std::endl;
262  for (unsigned ic = 0; ic < 8 && ic < size; ++ic) {
263  unsigned iq = localCellVector[ic];
264  // std::cout << " Testing " << EBDetId(regionOfInterest_[iq].getDetId()) << std::endl; ;
265  // std::cout << " " << iq << std::endl;
266  // std::cout << padsatdepth_[iq] ;
267  if (validPads_[iq] && padsatdepth_[iq].inside(point)) {
268  // std::cout << " Yes " << std::endl;
269  // myHistos->fill("h1000",niter);
270  sp = padsatdepth_[iq].survivalProbability();
271  // std::cout << "Finished the loop " << niter << std::endl;
272  // std::cout << "Inside " << std::endl;
273  return iq;
274  }
275  // std::cout << " Not inside " << std::endl;
276  // std::cout << "No " << std::endl;
277  }
278  }
279  if (debug)
280  std::cout << " not found in a quad, let's check the " << ncrackpadsatdepth_ << " cracks " << std::endl;
281  // std::cout << "Finished the loop " << niter << std::endl;
282  // Let's check the cracks
283  // std::cout << " Let's check the cracks " << ncrackpadsatdepth_ << " " << crackpadsatdepth_.size() << std::endl;
284  unsigned iquad = 0;
285  unsigned iquadinside = 999;
286  while (iquad < ncrackpadsatdepth_ && !found) {
287  // std::cout << " Inside the while " << std::endl;
288  if (crackpadsatdepth_[iquad].inside(point)) {
289  iquadinside = iquad;
290  found = true;
291  sp = crackpadsatdepth_[iquad].survivalProbability();
292  }
293  ++iquad;
294  }
295  // myHistos->fill("h1002",niter);
296  if (!found && debug)
297  std::cout << " Not found in the cracks " << std::endl;
298  return (found) ? crackpadsatdepth_[iquadinside].getNumber() : 9999;
299 }
300 
301 void EcalHitMaker::setTrackParameters(const XYZNormal& normal, double X0depthoffset, const FSimTrack& theTrack) {
302  // myHistos->debug("setTrackParameters");
303  // std::cout << " Track " << theTrack << std::endl;
304  intersections_.clear();
305  // This is certainly enough
306  intersections_.reserve(50);
307  myTrack_ = &theTrack;
308  normal_ = normal.Unit();
309  X0depthoffset_ = X0depthoffset;
312  // std::cout << " Segments " << segments_.size() << std::endl;
313  // for(unsigned ii=0; ii<segments_.size() ; ++ii)
314  // {
315  // std::cout << segments_[ii] << std::endl;
316  // }
317 
318  // This is only needed in case of electromagnetic showers
319  if (EMSHOWER && onEcal_ && ecalTotalX0() > 0.) {
320  // std::cout << "Total X0 " << ecalTotalX0() << std::endl;
321  for (unsigned ic = 0; ic < ncrystals_; ++ic) {
322  for (unsigned idir = 0; idir < 4; ++idir) {
323  XYZVector norm = regionOfInterest_[ic].exitingNormal(CaloDirectionOperations::Side(idir));
324  regionOfInterest_[ic].crystalNeighbour(idir).setToBeGlued((norm.Dot(normal_) < 0.));
325  }
326  // Now calculate the distance in X0 of the back sides of the crystals
327  // (only for EM showers)
328  if (EMSHOWER) {
329  XYZVector dir = regionOfInterest_[ic].getBackCenter() - segments_[ecalFirstSegment_].entrance();
330  double dist = dir.Dot(normal_);
331  double absciss = dist + segments_[ecalFirstSegment_].sEntrance();
332  std::vector<CaloSegment>::const_iterator segiterator;
333  // First identify the correct segment
334  // std::cout << " Crystal " << ic << regionOfInterest_[ic].getBackCenter() ;
335  // std::cout << " Entrance : " << segments_[ecalFirstSegment_].entrance()<< std::endl;
336  // std::cout << " Looking for the segment " << dist << std::endl;
337  segiterator = find_if(segments_.begin(), segments_.end(), CaloSegment::inSegment(absciss));
338  // std::cout << " Done " << std::endl;
339  if (segiterator == segments_.end()) {
340  // in this case, we won't have any problem. No need to
341  // calculate the real depth.
342  regionOfInterest_[ic].setX0Back(9999);
343  } else {
344  DetId::Detector det(segiterator->whichDetector());
345  if (det != DetId::Ecal) {
346  regionOfInterest_[ic].setX0Back(9999);
347  } else {
348  double x0 = segiterator->x0FromCm(dist);
349  if (x0 < maxX0_)
350  maxX0_ = x0;
351  regionOfInterest_[ic].setX0Back(x0);
352  }
353  }
354  // myHistos->fill("h4000",ecalentrance_.eta(), regionOfInterest_[ic].getX0Back());
355  //}
356  // else
357  //{
358  // // in this case, we won't have any problem. No need to
359  // // calculate the real depth.
360  // regionOfInterest_[ic].setX0Back(9999);
361  //}
362  } //EMSHOWER
363  } // ndir
364  // myHistos->fill("h6000",segments_[ecalFirstSegment_].entrance().eta(),maxX0_);
365  }
366  // std::cout << "Leaving setTrackParameters" << std::endl
367 }
368 
369 void EcalHitMaker::cellLine(std::vector<CaloPoint>& cp) {
370  cp.clear();
371  // if(myTrack->onVFcal()!=2)
372  // {
375  if (onEcal_)
377  // }
378 
379  XYZPoint vertex(myTrack_->vertex().position().Vect());
380 
381  //sort the points by distance (in the ECAL they are not necessarily ordered)
382  XYZVector dir(0., 0., 0.);
383  if (myTrack_->onLayer1()) {
384  vertex = (myTrack_->layer1Entrance().vertex()).Vect();
385  dir = myTrack_->layer1Entrance().Vect().Unit();
386  } else if (myTrack_->onLayer2()) {
387  vertex = (myTrack_->layer2Entrance().vertex()).Vect();
388  dir = myTrack_->layer2Entrance().Vect().Unit();
389  } else if (myTrack_->onEcal()) {
390  vertex = (myTrack_->ecalEntrance().vertex()).Vect();
391  dir = myTrack_->ecalEntrance().Vect().Unit();
392  } else if (myTrack_->onHcal()) {
393  vertex = (myTrack_->hcalEntrance().vertex()).Vect();
394  dir = myTrack_->hcalEntrance().Vect().Unit();
395  } else if (myTrack_->onVFcal() == 2) {
396  vertex = (myTrack_->vfcalEntrance().vertex()).Vect();
397  dir = myTrack_->vfcalEntrance().Vect().Unit();
398  } else {
399  std::cout << " Problem with the grid " << std::endl;
400  }
401 
402  // Move the vertex for distance comparison (5cm)
403  vertex -= 5. * dir;
405  sort(cp.begin(), cp.end(), myDistance);
406 
407  // The intersections with the HCAL shouldn't need to be sorted
408  // with the N.I it is actually a source of problems
409  hcalCellLine(cp);
410 
411  // std::cout << " Intersections ordered by distance to " << vertex << std::endl;
412  //
413  // for (unsigned ic=0;ic<cp.size();++ic)
414  // {
415  // XYZVector t=cp[ic]-vertex;
416  // std::cout << cp[ic] << " " << t.mag() << std::endl;
417  // }
418 }
419 
420 void EcalHitMaker::preshowerCellLine(std::vector<CaloPoint>& cp) const {
421  // FSimEvent& mySimEvent = myEventMgr->simSignal();
422  // FSimTrack myTrack = mySimEvent.track(fsimtrack_);
423  // std::cout << "FsimTrack " << fsimtrack_<< std::endl;
424  // std::cout << " On layer 1 " << myTrack.onLayer1() << std::endl;
425  // std::cout << " preshowerCellLine " << std::endl;
426  if (myTrack_->onLayer1()) {
427  XYZPoint point1 = (myTrack_->layer1Entrance().vertex()).Vect();
428  double phys_eta = myTrack_->layer1Entrance().eta();
429  double cmthickness = myCalorimeter->layer1Properties(1)->thickness(phys_eta);
430 
431  if (cmthickness > 0) {
432  XYZVector dir = myTrack_->layer1Entrance().Vect().Unit();
433  XYZPoint point2 = point1 + dir * cmthickness;
434 
435  CaloPoint cp1(DetId::Ecal, EcalPreshower, 1, point1);
436  CaloPoint cp2(DetId::Ecal, EcalPreshower, 1, point2);
437  cp.push_back(cp1);
438  cp.push_back(cp2);
439  } else {
440  // std::cout << "Track on ECAL " << myTrack.EcalEntrance_().vertex()*0.1<< std::endl;
441  }
442  }
443 
444  // std::cout << " On layer 2 " << myTrack.onLayer2() << std::endl;
445  if (myTrack_->onLayer2()) {
446  XYZPoint point1 = (myTrack_->layer2Entrance().vertex()).Vect();
447  double phys_eta = myTrack_->layer2Entrance().eta();
448  double cmthickness = myCalorimeter->layer2Properties(1)->thickness(phys_eta);
449  if (cmthickness > 0) {
450  XYZVector dir = myTrack_->layer2Entrance().Vect().Unit();
451  XYZPoint point2 = point1 + dir * cmthickness;
452 
453  CaloPoint cp1(DetId::Ecal, EcalPreshower, 2, point1);
454  CaloPoint cp2(DetId::Ecal, EcalPreshower, 2, point2);
455 
456  cp.push_back(cp1);
457  cp.push_back(cp2);
458  } else {
459  // std::cout << "Track on ECAL " << myTrack.EcalEntrance_().vertex()*0.1 << std::endl;
460  }
461  }
462  // std::cout << " Exit preshower CellLine " << std::endl;
463 }
464 
465 void EcalHitMaker::hcalCellLine(std::vector<CaloPoint>& cp) const {
466  // FSimEvent& mySimEvent = myEventMgr->simSignal();
467  // FSimTrack myTrack = mySimEvent.track(fsimtrack_);
468  int onHcal = myTrack_->onHcal();
469 
470  if (onHcal <= 2 && onHcal > 0) {
471  XYZPoint point1 = (myTrack_->hcalEntrance().vertex()).Vect();
472 
473  double eta = point1.eta();
474  // HCAL thickness in cm (assuming that the particle is coming from 000)
475  double thickness = myCalorimeter->hcalProperties(onHcal)->thickness(eta);
476  cp.push_back(CaloPoint(DetId::Hcal, point1));
477  XYZVector dir = myTrack_->hcalEntrance().Vect().Unit();
478  XYZPoint point2 = point1 + dir * thickness;
479 
480  cp.push_back(CaloPoint(DetId::Hcal, point2));
481  }
482  int onVFcal = myTrack_->onVFcal();
483  if (onVFcal == 2) {
484  XYZPoint point1 = (myTrack_->vfcalEntrance().vertex()).Vect();
485  double eta = point1.eta();
486  // HCAL thickness in cm (assuming that the particle is coming from 000)
488  cp.push_back(CaloPoint(DetId::Hcal, point1));
489  XYZVector dir = myTrack_->vfcalEntrance().Vect().Unit();
490  if (thickness > 0) {
491  XYZPoint point2 = point1 + dir * thickness;
492  cp.push_back(CaloPoint(DetId::Hcal, point2));
493  }
494  }
495 }
496 
497 void EcalHitMaker::ecalCellLine(const XYZPoint& a, const XYZPoint& b, std::vector<CaloPoint>& cp) {
498  // std::vector<XYZPoint> corners;
499  // corners.resize(4);
500  unsigned ic = 0;
501  double t;
502  XYZPoint xp;
503  DetId c_entrance, c_exit;
504  bool entrancefound(false), exitfound(false);
505  // std::cout << " Look for intersections " << ncrystals_ << std::endl;
506  // std::cout << " regionOfInterest_ " << truncatedGrid_ << " " << regionOfInterest_.size() << std::endl;
507  // try to determine the number of crystals to test
508  // First determine the incident angle
509  double angle = std::acos(normal_.Dot(regionOfInterest_[0].getAxis().Unit()));
510 
511  // std::cout << " Normal " << normal_<< " Axis " << regionOfInterest_[0].getAxis().Unit() << std::endl;
512  double backdistance = std::sqrt(regionOfInterest_[0].getAxis().mag2()) * std::tan(angle);
513  // 1/2.2cm = 0.45
514  // std::cout << " Angle " << angle << std::endl;
515  // std::cout << " Back distance " << backdistance << std::endl;
516  unsigned ncrystals = (unsigned)(backdistance * 0.45);
517  unsigned highlim = (ncrystals + 4);
518  highlim *= highlim;
519  if (highlim > ncrystals_)
520  highlim = ncrystals_;
521  // unsigned lowlim=(ncrystals>2)? (ncrystals-2):0;
522  // std::cout << " Ncrys " << ncrystals << std::endl;
523 
524  while (ic < ncrystals_ && (ic < highlim || !exitfound)) {
525  // Check front side
526  // if(!entrancefound)
527  {
528  const Plane3D& plan = regionOfInterest_[ic].getFrontPlane();
529  // XYZVector axis1=(plan.Normal());
530  // XYZVector axis2=regionOfInterest_[ic].getFirstEdge();
531  xp = intersect(plan, a, b, t, false);
532  regionOfInterest_[ic].getFrontSide(corners);
533  // CrystalPad pad(9999,onEcal_,corners,regionOfInterest_[ic].getCorner(0),axis1,axis2);
534  // if(pad.globalinside(xp))
535  if (inside3D(corners, xp)) {
536  cp.push_back(CaloPoint(regionOfInterest_[ic].getDetId(), UP, xp));
537  entrancefound = true;
538  c_entrance = regionOfInterest_[ic].getDetId();
539  // myHistos->fill("j12",highlim,ic);
540  }
541  }
542 
543  // check rear side
544  // if(!exitfound)
545  {
546  const Plane3D& plan = regionOfInterest_[ic].getBackPlane();
547  // XYZVector axis1=(plan.Normal());
548  // XYZVector axis2=regionOfInterest_[ic].getFifthEdge();
549  xp = intersect(plan, a, b, t, false);
550  regionOfInterest_[ic].getBackSide(corners);
551  // CrystalPad pad(9999,onEcal_,corners,regionOfInterest_[ic].getCorner(4),axis1,axis2);
552  // if(pad.globalinside(xp))
553  if (inside3D(corners, xp)) {
554  cp.push_back(CaloPoint(regionOfInterest_[ic].getDetId(), DOWN, xp));
555  exitfound = true;
556  c_exit = regionOfInterest_[ic].getDetId();
557  // std::cout << " Crystal : " << ic << std::endl;
558  // myHistos->fill("j10",highlim,ic);
559  }
560  }
561 
562  if (entrancefound && exitfound && c_entrance == c_exit)
563  return;
564  // check lateral sides
565  for (unsigned iside = 0; iside < 4; ++iside) {
566  const Plane3D& plan = regionOfInterest_[ic].getLateralPlane(iside);
567  xp = intersect(plan, a, b, t, false);
568  // XYZVector axis1=(plan.Normal());
569  // XYZVector axis2=regionOfInterest_[ic].getLateralEdge(iside);
570  regionOfInterest_[ic].getLateralSide(iside, corners);
571  // CrystalPad pad(9999,onEcal_,corners,regionOfInterest_[ic].getCorner(iside),axis1,axis2);
572  // if(pad.globalinside(xp))
573  if (inside3D(corners, xp)) {
574  cp.push_back(CaloPoint(regionOfInterest_[ic].getDetId(), CaloDirectionOperations::Side(iside), xp));
575  // std::cout << cp[cp.size()-1] << std::endl;
576  }
577  }
578  // Go to next crystal
579  ++ic;
580  }
581 }
582 
583 void EcalHitMaker::buildSegments(const std::vector<CaloPoint>& cp) {
584  // myHistos->debug();
585  // TimeMe theT("FamosGrid::buildSegments");
586  unsigned size = cp.size();
587  if (size % 2 != 0) {
588  // std::cout << " There is a problem " << std::endl;
589  return;
590  }
591  // myHistos->debug();
592  unsigned nsegments = size / 2;
593  segments_.reserve(nsegments);
594  if (size == 0)
595  return;
596  // curv abs
597  double s = 0.;
598  double sX0 = 0.;
599  double sL0 = 0.;
600 
601 #ifdef DEBUGCELLLINE
602  unsigned ncrossedxtals = 0;
603 #endif
604  unsigned is = 0;
605  while (is < nsegments) {
606  if (cp[2 * is].getDetId() != cp[2 * is + 1].getDetId() && cp[2 * is].whichDetector() != DetId::Hcal &&
607  cp[2 * is + 1].whichDetector() != DetId::Hcal) {
608  // std::cout << " Problem with the segments " << std::endl;
609  // std::cout << cp[2*is].whichDetector() << " " << cp[2*is+1].whichDetector() << std::endl;
610  // std::cout << is << " " <<cp[2*is].getDetId().rawId() << std::endl;
611  // std::cout << (2*is+1) << " " <<cp[2*is+1].getDetId().rawId() << std::endl;
612  ++is;
613  continue;
614  }
615 
616  // Check if it is a Preshower segment - Layer 1
617  // One segment per layer, nothing between
618  // myHistos->debug("Just avant Preshower");
619  if (cp[2 * is].whichDetector() == DetId::Ecal && cp[2 * is].whichSubDetector() == EcalPreshower &&
620  cp[2 * is].whichLayer() == 1) {
621  if (cp[2 * is + 1].whichDetector() == DetId::Ecal && cp[2 * is + 1].whichSubDetector() == EcalPreshower &&
622  cp[2 * is + 1].whichLayer() == 1) {
623  CaloSegment preshsegment(cp[2 * is], cp[2 * is + 1], s, sX0, sL0, CaloSegment::PS, myCalorimeter);
624  segments_.push_back(preshsegment);
625  // std::cout << " Added (1-1)" << preshsegment << std::endl;
626  s += preshsegment.length();
627  sX0 += preshsegment.X0length();
628  sL0 += preshsegment.L0length();
629  X0PS1_ += preshsegment.X0length();
630  L0PS1_ += preshsegment.L0length();
631  } else {
632  std::cout << " Strange segment between Preshower1 and " << cp[2 * is + 1].whichDetector();
633  std::cout << std::endl;
634  }
635  ++is;
636  continue;
637  }
638 
639  // Check if it is a Preshower segment - Layer 2
640  // One segment per layer, nothing between
641  if (cp[2 * is].whichDetector() == DetId::Ecal && cp[2 * is].whichSubDetector() == EcalPreshower &&
642  cp[2 * is].whichLayer() == 2) {
643  if (cp[2 * is + 1].whichDetector() == DetId::Ecal && cp[2 * is + 1].whichSubDetector() == EcalPreshower &&
644  cp[2 * is + 1].whichLayer() == 2) {
645  CaloSegment preshsegment(cp[2 * is], cp[2 * is + 1], s, sX0, sL0, CaloSegment::PS, myCalorimeter);
646  segments_.push_back(preshsegment);
647  // std::cout << " Added (1-2)" << preshsegment << std::endl;
648  s += preshsegment.length();
649  sX0 += preshsegment.X0length();
650  sL0 += preshsegment.L0length();
651  X0PS2_ += preshsegment.X0length();
652  L0PS2_ += preshsegment.L0length();
653 
654  // material between preshower and EE
655  if (is < (nsegments - 1) && cp[2 * is + 2].whichDetector() == DetId::Ecal &&
656  cp[2 * is + 2].whichSubDetector() == EcalEndcap) {
657  CaloSegment gapsef(cp[2 * is + 1], cp[2 * is + 2], s, sX0, sL0, CaloSegment::PSEEGAP, myCalorimeter);
658  segments_.push_back(gapsef);
659  s += gapsef.length();
660  sX0 += gapsef.X0length();
661  sL0 += gapsef.L0length();
662  X0PS2EE_ += gapsef.X0length();
663  L0PS2EE_ += gapsef.L0length();
664  // std::cout << " Created a segment " << gapsef.length()<< " " << gapsef.X0length()<< std::endl;
665  }
666  } else {
667  std::cout << " Strange segment between Preshower2 and " << cp[2 * is + 1].whichDetector();
668  std::cout << std::endl;
669  }
670  ++is;
671  continue;
672  }
673  // Now deal with the ECAL
674  // One segment in each crystal. Segment corresponding to cracks/gaps are added
675  // myHistos->debug("Just avant ECAL");
676  if (cp[2 * is].whichDetector() == DetId::Ecal &&
677  (cp[2 * is].whichSubDetector() == EcalBarrel || cp[2 * is].whichSubDetector() == EcalEndcap)) {
678  if (cp[2 * is + 1].whichDetector() == DetId::Ecal &&
679  (cp[2 * is + 1].whichSubDetector() == EcalBarrel || cp[2 * is + 1].whichSubDetector() == EcalEndcap)) {
680  DetId cell2 = cp[2 * is + 1].getDetId();
681  // set the real entrance
682  if (ecalFirstSegment_ < 0)
683  ecalFirstSegment_ = segments_.size();
684 
685  // !! Approximatiom : the first segment is always in a crystal
686  if (cp[2 * is].getDetId() == cell2) {
687  CaloSegment segment(cp[2 * is], cp[2 * is + 1], s, sX0, sL0, CaloSegment::PbWO4, myCalorimeter);
688  segments_.push_back(segment);
689  // std::cout << " Added (2)" << segment << std::endl;
690  s += segment.length();
691  sX0 += segment.X0length();
692  sL0 += segment.L0length();
693  X0ECAL_ += segment.X0length();
694  L0ECAL_ += segment.L0length();
695 #ifdef DEBUGCELLLINE
696  ++ncrossedxtals;
697 #endif
698  ++is;
699  } else {
700  std::cout << " One more bug in the segment " << std::endl;
701  ++is;
702  }
703  // Now check if a gap or crack should be added
704  if (is > 0 && is < nsegments) {
705  DetId cell3 = cp[2 * is].getDetId();
706  if (cp[2 * is].whichDetector() != DetId::Hcal) {
707  // Crack inside the ECAL
708  bool bordercrossing = myCalorimeter->borderCrossing(cell2, cell3);
709  CaloSegment cracksegment(cp[2 * is - 1],
710  cp[2 * is],
711  s,
712  sX0,
713  sL0,
714  (bordercrossing) ? CaloSegment::CRACK : CaloSegment::GAP,
715  myCalorimeter);
716  segments_.push_back(cracksegment);
717  s += cracksegment.length();
718  sX0 += cracksegment.X0length();
719  sL0 += cracksegment.L0length();
720  X0ECAL_ += cracksegment.X0length();
721  L0ECAL_ += cracksegment.L0length();
722  // std::cout <<" Added(3) "<< cracksegment << std::endl;
723  } else {
724  // a segment corresponding to ECAL/HCAL transition should be
725  // added here
726  CaloSegment cracksegment(cp[2 * is - 1], cp[2 * is], s, sX0, sL0, CaloSegment::ECALHCALGAP, myCalorimeter);
727  segments_.push_back(cracksegment);
728  s += cracksegment.length();
729  sX0 += cracksegment.X0length();
730  sL0 += cracksegment.L0length();
731  X0EHGAP_ += cracksegment.X0length();
732  L0EHGAP_ += cracksegment.L0length();
733  }
734  }
735  continue;
736  } else {
737  std::cout << " Strange segment between " << cp[2 * is].whichDetector();
738  std::cout << " and " << cp[2 * is + 1].whichDetector() << std::endl;
739  ++is;
740  continue;
741  }
742  }
743  // myHistos->debug("Just avant HCAL");
744  // HCAL
745  if (cp[2 * is].whichDetector() == DetId::Hcal && cp[2 * is + 1].whichDetector() == DetId::Hcal) {
746  CaloSegment segment(cp[2 * is], cp[2 * is + 1], s, sX0, sL0, CaloSegment::HCAL, myCalorimeter);
747  segments_.push_back(segment);
748  s += segment.length();
749  sX0 += segment.X0length();
750  sL0 += segment.L0length();
751  X0HCAL_ += segment.X0length();
752  L0HCAL_ += segment.L0length();
753  // std::cout <<" Added(4) "<< segment << std::endl;
754  ++is;
755  }
756  }
757  // std::cout << " PS1 " << X0PS1_ << " " << L0PS1_ << std::endl;
758  // std::cout << " PS2 " << X0PS2_ << " " << L0PS2_ << std::endl;
759  // std::cout << " ECAL " << X0ECAL_ << " " << L0ECAL_ << std::endl;
760  // std::cout << " HCAL " << X0HCAL_ << " " << L0HCAL_ << std::endl;
761 
764  // myHistos->debug("Just avant le fill");
765 
766 #ifdef DEBUGCELLLINE
767  myHistos->fill("h200", fabs(EcalEntrance_.eta()), X0ECAL_);
768  myHistos->fill("h210", EcalEntrance_.phi(), X0ECAL_);
769  if (X0ECAL_ < 20)
770  myHistos->fill("h212", EcalEntrance_.phi(), X0ECAL_);
771  // if(X0ECAL_<1.)
772  // {
773  // for(unsigned ii=0; ii<segments_.size() ; ++ii)
774  // {
775  // std::cout << segments_[ii] << std::endl;
776  // }
777  // }
778  myHistos->fillByNumber("h30", ncrossedxtals, EcalEntrance_.eta(), X0ECAL_);
779 
780  double zvertex = myTrack_->vertex().position().z();
781 
782  myHistos->fill("h310", EcalEntrance_.eta(), X0ECAL_);
783  if (X0ECAL_ < 22)
784  myHistos->fill("h410", EcalEntrance_.phi());
785  myHistos->fill("h400", zvertex, X0ECAL_);
786 #endif
787  // std::cout << " Finished the segments " << std::endl;
788 }
789 
791  configuredGeometry_ = false;
792  ncrystals_ = CellsWindow_.size();
793  // create the vector with of pads with the appropriate size
794  padsatdepth_.resize(ncrystals_);
795 
796  // This is fully correct in the barrel.
797  ny_ = phisize_;
798  nx_ = ncrystals_ / ny_;
799  std::vector<unsigned> empty;
800  empty.resize(ny_, 0);
801  myCrystalNumberArray_.reserve((unsigned)nx_);
802  for (unsigned inx = 0; inx < (unsigned)nx_; ++inx) {
803  myCrystalNumberArray_.push_back(empty);
804  }
805 
806  hits_.resize(ncrystals_, 0.);
807  regionOfInterest_.clear();
809  validPads_.resize(ncrystals_);
810  for (unsigned ic = 0; ic < ncrystals_; ++ic) {
812  regionOfInterest_[ic].setNumber(ic);
813  DetIdMap_.insert(std::pair<DetId, unsigned>(CellsWindow_[ic], ic));
814  }
815 
816  // Computes the map of the neighbours
818 }
819 
820 // depth is in X0 , L0 (depending on EMSHOWER/HADSHOWER) or in CM if inCM
821 bool EcalHitMaker::getPads(double depth, bool inCm) {
822  //std::cout << " New depth " << depth << std::endl;
823  // The first time, the relationship between crystals must be calculated
824  // but only in the case of EM showers
825 
828 
830  detailedShowerTail_ = false;
831  if (EMSHOWER)
833  else
835 
836  // if(currentdepth_>maxX0_+ps1TotalX0()+ps2TotalX0())
837  // {
838  // currentdepth_=maxX0_+ps1TotalX0()+ps2TotalX0()-1.; // the -1 is for safety
839  // detailedShowerTail_=true;
840  // }
841 
842  // std::cout << " FamosGrid::getQuads " << currentdepth_ << " " << maxX0_ << std::endl;
843 
844  ncrackpadsatdepth_ = 0;
845 
846  xmin_ = ymin_ = 999;
847  xmax_ = ymax_ = -999;
848  double locxmin, locxmax, locymin, locymax;
849 
850  // Get the depth of the pivot
851  std::vector<CaloSegment>::const_iterator segiterator;
852  // First identify the correct segment
853 
854  if (inCm) // centimeter
855  {
856  segiterator = find_if(segments_.begin(), segments_.end(), CaloSegment::inSegment(currentdepth_));
857  } else {
858  // EM shower
859  if (EMSHOWER)
860  segiterator = find_if(segments_.begin(), segments_.end(), CaloSegment::inX0Segment(currentdepth_));
861 
862  //Hadron shower
863  if (HADSHOWER)
864  segiterator = find_if(segments_.begin(), segments_.end(), CaloSegment::inL0Segment(currentdepth_));
865  }
866  if (segiterator == segments_.end()) {
867  std::cout << " FamosGrid: Could not go at such depth " << depth << std::endl;
868  std::cout << " EMSHOWER " << EMSHOWER << std::endl;
869  std::cout << " Track " << *myTrack_ << std::endl;
870  std::cout << " Segments " << segments_.size() << std::endl;
871  for (unsigned ii = 0; ii < segments_.size(); ++ii) {
872  std::cout << segments_[ii] << std::endl;
873  }
874 
875  return false;
876  }
877  // std::cout << *segiterator << std::endl;
878 
879  if (segiterator->whichDetector() != DetId::Ecal) {
880  std::cout << " In " << segiterator->whichDetector() << std::endl;
881  // buildPreshower();
882  return false;
883  }
884 
885  // std::cout << *segiterator << std::endl;
886  // get the position of the origin
887 
888  XYZPoint origin;
889  if (inCm) {
890  origin = segiterator->positionAtDepthincm(currentdepth_);
891  } else {
892  if (EMSHOWER)
893  origin = segiterator->positionAtDepthinX0(currentdepth_);
894  if (HADSHOWER)
895  origin = segiterator->positionAtDepthinL0(currentdepth_);
896  }
897  // std::cout << " currentdepth_ " << currentdepth_ << " " << origin << std::endl;
898  XYZVector newaxis = pivot_.getFirstEdge().Cross(normal_);
899 
900  // std::cout << "Normal " << normal_ << std::endl;
901  // std::cout << " New axis " << newaxis << std::endl;
902 
903  // std::cout << " ncrystals " << ncrystals << std::endl;
904  plan_ = Plane3D((Vector)normal_, (Point)origin);
905 
906  unsigned nquads = 0;
907  double sign = (central_) ? -1. : 1.;
908  Transform3DR trans((Point)origin,
909  (Point)(origin + normal_),
910  (Point)(origin + newaxis),
911  Point(0, 0, 0),
912  Point(0., 0., sign),
913  Point(0., 1., 0.));
914  for (unsigned ic = 0; ic < ncrystals_; ++ic) {
915  // std::cout << " Building geometry for " << regionOfInterest_[ic].getCellID() << std::endl;
916  XYZPoint a, b;
917 
918  // std::cout << " Origin " << origin << std::endl;
919 
920  // std::vector<XYZPoint> corners;
921  // corners.reserve(4);
922  double dummyt;
923  bool hasbeenpulled = false;
924  bool behindback = false;
925  for (unsigned il = 0; il < 4; ++il) {
926  // a is the il-th front corner of the crystal. b is the corresponding rear corner
927  regionOfInterest_[ic].getLateralEdges(il, a, b);
928 
929  // pull the surface if necessary (only in the front of the crystals)
930  XYZPoint aprime = a;
931  if (pulled(origin, normal_, a)) {
932  b = aprime;
933  hasbeenpulled = true;
934  }
935 
936  // compute the intersection.
937  // Check that the intersection is in the [a,b] segment if HADSHOWER
938  // if EMSHOWER the intersection is calculated as if the crystals were infinite
939  XYZPoint xx = (EMSHOWER) ? intersect(plan_, a, b, dummyt, false) : intersect(plan_, a, b, dummyt, true);
940 
941  if (dummyt > 1)
942  behindback = true;
943  // std::cout << " Intersect " << il << " " << a << " " << b << " " << plan_ << " " << xx << std::endl;
944  // check that the intersection actually exists
945  if (xx.mag2() != 0) {
946  corners[il] = xx;
947  }
948  }
949  // std::cout << " ncorners " << corners.size() << std::endl;
950  if (behindback && EMSHOWER)
951  detailedShowerTail_ = true;
952  // If the quad is completly defined. Store it !
953  if (corners.size() == 4) {
954  padsatdepth_[ic] = CrystalPad(ic, corners, trans, bfactor_, !central_);
955  // Parameter to be tuned
956  if (hasbeenpulled)
957  padsatdepth_[ic].setSurvivalProbability(pulledPadProbability_);
958  validPads_[ic] = true;
959  ++nquads;
960  // In principle, this should be done after the quads reorganization. But it would cost one more loop
961  // quadsatdepth_[ic].extrems(locxmin,locxmax,locymin,locymax);
962  // if(locxmin<xmin_) xmin_=locxmin;
963  // if(locymin<ymin_) ymin_=locymin;
964  // if(locxmax>xmax_) xmax_=locxmax;
965  // if(locymax>ymax_) ymax_=locymax;
966  } else {
967  padsatdepth_[ic] = CrystalPad();
968  validPads_[ic] = false;
969  }
970  }
971  // std::cout << " Number of quads " << quadsatdepth_.size() << std::endl;
972  if (doreorg_)
973  reorganizePads();
974  // std::cout << "Finished to reorganize " << std::endl;
975  npadsatdepth_ = nquads;
976  // std::cout << " prepareCellIDMap " << std::endl;
977 
978  // Resize the Quads to allow for some numerical inaccuracy
979  // in the "inside" function
980  for (unsigned ic = 0; ic < ncrystals_; ++ic) {
981  if (!validPads_[ic])
982  continue;
983 
984  if (EMSHOWER)
985  padsatdepth_[ic].resetCorners();
986 
987  padsatdepth_[ic].extrems(locxmin, locxmax, locymin, locymax);
988  if (locxmin < xmin_)
989  xmin_ = locxmin;
990  if (locymin < ymin_)
991  ymin_ = locymin;
992  if (locxmax > xmax_)
993  xmax_ = locxmax;
994  if (locymax > ymax_)
995  ymax_ = locymax;
996  }
997 
998  sizex_ = (xmax_ - xmin_) / nx_;
999  sizey_ = (ymax_ - ymin_) / ny_;
1000 
1001  // Make sure that sizex_ and sizey_ are set before running prepareCellIDMap
1003 
1004  // std::cout << " Finished prepareCellIDMap " << std::endl;
1006 
1007  return true;
1008 }
1009 
1011  configuredGeometry_ = true;
1012  for (unsigned ic = 0; ic < ncrystals_; ++ic) {
1013  // std::cout << " Building " << cellids_[ic] << std::endl;
1014  for (unsigned idir = 0; idir < 8; ++idir) {
1015  unsigned oppdir = CaloDirectionOperations::oppositeDirection(idir);
1016  // Is there something else to do ?
1017  // The relationship with the neighbour may have been set previously.
1018  if (regionOfInterest_[ic].crystalNeighbour(idir).status() >= 0) {
1019  // std::cout << " Nothing to do " << std::endl;
1020  continue;
1021  }
1022 
1023  const DetId& oldcell(regionOfInterest_[ic].getDetId());
1025  DetId newcell(oldcell);
1026  if (!myCalorimeter->move(newcell, dir)) {
1027  // no neighbour in this direction
1028  regionOfInterest_[ic].crystalNeighbour(idir).setStatus(-1);
1029  continue;
1030  }
1031  // Determine the number of this neighbour
1032  // std::cout << " The neighbour is " << newcell << std::endl;
1033  std::map<DetId, unsigned>::const_iterator niter(DetIdMap_.find(newcell));
1034  if (niter == DetIdMap_.end()) {
1035  // std::cout << " The neighbour is not in the map " << std::endl;
1036  regionOfInterest_[ic].crystalNeighbour(idir).setStatus(-1);
1037  continue;
1038  }
1039  // Now there is a neighbour
1040  // std::cout << " The neighbour is " << niter->second << " " << cellids_[niter->second] << std::endl;
1041  regionOfInterest_[ic].crystalNeighbour(idir).setNumber(niter->second);
1042  // std::cout << " Managed to set crystalNeighbour " << ic << " " << idir << std::endl;
1043  // std::cout << " Trying " << niter->second << " " << oppdir << std::endl;
1044  regionOfInterest_[niter->second].crystalNeighbour(oppdir).setNumber(ic);
1045  // std::cout << " Crack/gap " << std::endl;
1046  if (myCalorimeter->borderCrossing(oldcell, newcell)) {
1047  regionOfInterest_[ic].crystalNeighbour(idir).setStatus(1);
1048  regionOfInterest_[niter->second].crystalNeighbour(oppdir).setStatus(1);
1049  // std::cout << " Crack ! " << std::endl;
1050  } else {
1051  regionOfInterest_[ic].crystalNeighbour(idir).setStatus(0);
1052  regionOfInterest_[niter->second].crystalNeighbour(oppdir).setStatus(0);
1053  // std::cout << " Gap" << std::endl;
1054  }
1055  }
1056  }
1057  // Magnetic field a la Charlot
1058  double theta = EcalEntrance_.theta();
1059  if (theta > M_PI_2)
1060  theta = M_PI - theta;
1061  bfactor_ = 1. / (1. + 0.133 * theta);
1062  if (myCalorimeter->magneticField() == 0.)
1063  bfactor_ = 1.;
1064 }
1065 
1066 // project fPoint on the plane (original,normal)
1067 bool EcalHitMaker::pulled(const XYZPoint& origin, const XYZNormal& normal, XYZPoint& fPoint) const {
1068  // check if fPoint is behind the origin
1069  double dotproduct = normal.Dot(fPoint - origin);
1070  if (dotproduct <= 0.)
1071  return false;
1072 
1073  //norm of normal is 1
1074  fPoint -= (1 + dotproduct) * normal;
1075  return true;
1076 }
1077 
1079  for (unsigned iq = 0; iq < npadsatdepth_; ++iq) {
1080  if (!validPads_[iq])
1081  continue;
1082  unsigned d1, d2;
1083  convertIntegerCoordinates(padsatdepth_[iq].center().x(), padsatdepth_[iq].center().y(), d1, d2);
1084  myCrystalNumberArray_[d1][d2] = iq;
1085  }
1086 }
1087 
1088 void EcalHitMaker::convertIntegerCoordinates(double x, double y, unsigned& ix, unsigned& iy) const {
1089  int tix = (int)((x - xmin_) / sizex_);
1090  int tiy = (int)((y - ymin_) / sizey_);
1091  ix = iy = 9999;
1092  if (tix >= 0)
1093  ix = (unsigned)tix;
1094  if (tiy >= 0)
1095  iy = (unsigned)tiy;
1096 }
1097 
1098 const std::map<CaloHitID, float>& EcalHitMaker::getHits() {
1100  return hitMap_;
1101  for (unsigned ic = 0; ic < ncrystals_; ++ic) {
1102  //calculate time of flight
1103  float tof = 0.0;
1104  if (onEcal_ == 1 || onEcal_ == 2)
1105  tof =
1106  (myCalorimeter->getEcalGeometry(onEcal_)->getGeometry(regionOfInterest_[ic].getDetId())->getPosition().mag()) /
1107  29.98; //speed of light
1108 
1109  if (onEcal_ == 1) {
1110  CaloHitID current_id(EBDetId(regionOfInterest_[ic].getDetId().rawId()).hashedIndex(), tof, 0); //no track yet
1111  hitMap_.insert(std::pair<CaloHitID, float>(current_id, hits_[ic]));
1112  } else if (onEcal_ == 2) {
1113  CaloHitID current_id(EEDetId(regionOfInterest_[ic].getDetId().rawId()).hashedIndex(), tof, 0); //no track yet
1114  hitMap_.insert(std::pair<CaloHitID, float>(current_id, hits_[ic]));
1115  }
1116  }
1117  hitmaphasbeencalculated_ = true;
1118  return hitMap_;
1119 }
1120 
1122 
1124  // Some cleaning first
1125  // std::cout << " Starting reorganize " << std::endl;
1126  crackpadsatdepth_.clear();
1127  crackpadsatdepth_.reserve(etasize_ * phisize_);
1128  ncrackpadsatdepth_ = 0;
1129  std::vector<neighbour> gaps;
1130  std::vector<std::vector<neighbour> > cracks;
1131  // cracks.clear();
1132  cracks.resize(ncrystals_);
1133 
1134  for (unsigned iq = 0; iq < ncrystals_; ++iq) {
1135  if (!validPads_[iq])
1136  continue;
1137 
1138  gaps.clear();
1139  // std::cout << padsatdepth_[iq] << std::endl;
1140  //check all the directions
1141  for (unsigned iside = 0; iside < 4; ++iside) {
1142  // std::cout << " To be glued " << iside << " " << regionOfInterest_[iq].crystalNeighbour(iside).toBeGlued() << std::endl;
1143  CaloDirection thisside = CaloDirectionOperations::Side(iside);
1144  if (regionOfInterest_[iq].crystalNeighbour(iside).toBeGlued()) {
1145  // look for the neighbour and check that it exists
1146  int neighbourstatus = regionOfInterest_[iq].crystalNeighbour(iside).status();
1147  if (neighbourstatus < 0)
1148  continue;
1149 
1150  unsigned neighbourNumber = regionOfInterest_[iq].crystalNeighbour(iside).number();
1151  if (!validPads_[neighbourNumber])
1152  continue;
1153  // there is a crack between
1154  if (neighbourstatus == 1) {
1155  // std::cout << " 1 Crack : " << thisside << " " << cellids_[iq]<< " " << cellids_[neighbourNumber] << std::endl;
1156  cracks[iq].push_back(neighbour(thisside, neighbourNumber));
1157  } // else it is a gap
1158  else {
1159  gaps.push_back(neighbour(thisside, neighbourNumber));
1160  }
1161  }
1162  }
1163  // Now lift the gaps
1164  gapsLifting(gaps, iq);
1165  }
1166 
1167  unsigned ncracks = cracks.size();
1168  // std::cout << " Cracks treatment : " << cracks.size() << std::endl;
1169  for (unsigned icrack = 0; icrack < ncracks; ++icrack) {
1170  // std::cout << " Crack number " << crackiter->first << std::endl;
1171  cracksPads(cracks[icrack], icrack);
1172  }
1173 }
1174 
1175 //dir 2 = N,E,W,S
1179  // std::cout << "Corresponding Edge " << dir<< " " << dir2 << " " << corner << std::endl;
1180  return padsatdepth_[myneighbour.second].edge(corner);
1181 }
1182 
1183 bool EcalHitMaker::diagonalEdge(unsigned myPad, CaloDirection dir, CLHEP::Hep2Vector& point) {
1185  if (regionOfInterest_[myPad].crystalNeighbour(idir).status() < 0)
1186  return false;
1187  unsigned nneighbour = regionOfInterest_[myPad].crystalNeighbour(idir).number();
1188  if (!validPads_[nneighbour]) {
1189  // std::cout << " Wasn't able to move " << std::endl;
1190  return false;
1191  }
1193  return true;
1194 }
1195 
1196 bool EcalHitMaker::unbalancedDirection(const std::vector<neighbour>& dirs,
1197  unsigned& unb,
1198  unsigned& dir1,
1199  unsigned& dir2) {
1200  if (dirs.size() == 1)
1201  return false;
1202  if (dirs.size() % 2 == 0)
1203  return false;
1206  if (tmp == NONE) {
1207  unb = 2;
1208  dir1 = 0;
1209  dir2 = 1;
1210  return true;
1211  }
1213  if (tmp == NONE) {
1214  unb = 1;
1215  dir1 = 0;
1216  dir2 = 2;
1217  return true;
1218  }
1219  unb = 0;
1220  dir1 = 1;
1221  dir2 = 2;
1222  return true;
1223 }
1224 
1225 void EcalHitMaker::gapsLifting(std::vector<neighbour>& gaps, unsigned iq) {
1226  // std::cout << " Entering gapsLifting " << std::endl;
1227  CrystalPad& myPad = padsatdepth_[iq];
1228  unsigned ngaps = gaps.size();
1229  constexpr bool debug = false;
1230  if (ngaps == 1) {
1231  if (debug) {
1232  std::cout << " Avant " << ngaps << " " << gaps[0].first << std::endl;
1233  std::cout << myPad << std::endl;
1234  }
1235  if (gaps[0].first == NORTH || gaps[0].first == SOUTH) {
1238  myPad.edge(dir1) = correspondingEdge(gaps[0], EAST);
1239  myPad.edge(dir2) = correspondingEdge(gaps[0], WEST);
1240  } else {
1243  myPad.edge(dir1) = correspondingEdge(gaps[0], NORTH);
1244  myPad.edge(dir2) = correspondingEdge(gaps[0], SOUTH);
1245  }
1246  if (debug) {
1247  std::cout << " Apres " << std::endl;
1248  std::cout << myPad << std::endl;
1249  }
1250  } else if (ngaps == 2) {
1251  if (debug) {
1252  std::cout << " Avant " << ngaps << " " << gaps[0].first << " " << gaps[1].first << std::endl;
1253  std::cout << myPad << std::endl;
1254  std::cout << " Voisin 1 " << (gaps[0].second) << std::endl;
1255  std::cout << " Voisin 2 " << (gaps[1].second) << std::endl;
1256  }
1257  CaloDirection corner0 = CaloDirectionOperations::add2d(gaps[0].first, gaps[1].first);
1258 
1259  CLHEP::Hep2Vector point(0., 0.);
1260  if (corner0 != NONE && diagonalEdge(iq, corner0, point)) {
1261  CaloDirection corner1 =
1263  CaloDirection corner2 =
1265  myPad.edge(corner0) = point;
1266  myPad.edge(corner1) = correspondingEdge(gaps[1], CaloDirectionOperations::oppositeSide(gaps[0].first));
1267  myPad.edge(corner2) = correspondingEdge(gaps[0], CaloDirectionOperations::oppositeSide(gaps[1].first));
1268  } else if (corner0 == NONE) {
1269  if (gaps[0].first == EAST || gaps[0].first == WEST) {
1272  myPad.edge(corner1) = correspondingEdge(gaps[0], NORTH);
1273  myPad.edge(corner2) = correspondingEdge(gaps[0], SOUTH);
1274 
1275  corner1 = CaloDirectionOperations::add2d(gaps[1].first, NORTH);
1276  corner2 = CaloDirectionOperations::add2d(gaps[1].first, SOUTH);
1277  myPad.edge(corner1) = correspondingEdge(gaps[1], NORTH);
1278  myPad.edge(corner2) = correspondingEdge(gaps[1], SOUTH);
1279  } else {
1282  myPad.edge(corner1) = correspondingEdge(gaps[0], EAST);
1283  myPad.edge(corner2) = correspondingEdge(gaps[0], WEST);
1284 
1285  corner1 = CaloDirectionOperations::add2d(gaps[1].first, EAST);
1286  corner2 = CaloDirectionOperations::add2d(gaps[1].first, WEST);
1287  myPad.edge(corner1) = correspondingEdge(gaps[1], EAST);
1288  myPad.edge(corner2) = correspondingEdge(gaps[1], WEST);
1289  }
1290  }
1291  if (debug) {
1292  std::cout << " Apres " << std::endl;
1293  std::cout << myPad << std::endl;
1294  }
1295  } else if (ngaps == 3) {
1296  // in this case the four corners have to be changed
1297  unsigned iubd, idir1, idir2;
1298  CaloDirection diag;
1299  CLHEP::Hep2Vector point(0., 0.);
1300  // std::cout << " Yes : 3 gaps" << std::endl;
1301  if (unbalancedDirection(gaps, iubd, idir1, idir2)) {
1302  CaloDirection ubd(gaps[iubd].first), dir1(gaps[idir1].first);
1303  CaloDirection dir2(gaps[idir2].first);
1304 
1305  // std::cout << " Avant " << std::endl << myPad << std::endl;
1306  // std::cout << ubd << " " << dir1 << " " << dir2 << std::endl;
1307  diag = CaloDirectionOperations::add2d(ubd, dir1);
1308  if (diagonalEdge(iq, diag, point))
1309  myPad.edge(diag) = point;
1310  diag = CaloDirectionOperations::add2d(ubd, dir2);
1311  if (diagonalEdge(iq, diag, point))
1312  myPad.edge(diag) = point;
1314  myPad.edge(CaloDirectionOperations::add2d(oppside, dir1)) = correspondingEdge(gaps[idir1], oppside);
1315  myPad.edge(CaloDirectionOperations::add2d(oppside, dir2)) = correspondingEdge(gaps[idir2], oppside);
1316  // std::cout << " Apres " << std::endl << myPad << std::endl;
1317  }
1318  } else if (ngaps == 4) {
1319  // std::cout << " Waouh :4 gaps" << std::endl;
1320  // std::cout << " Avant " << std::endl;
1321  // std::cout << myPad<< std::endl;
1322  CLHEP::Hep2Vector point(0., 0.);
1323  if (diagonalEdge(iq, NORTHEAST, point))
1324  myPad.edge(NORTHEAST) = point;
1325  if (diagonalEdge(iq, NORTHWEST, point))
1326  myPad.edge(NORTHWEST) = point;
1327  if (diagonalEdge(iq, SOUTHWEST, point))
1328  myPad.edge(SOUTHWEST) = point;
1329  if (diagonalEdge(iq, SOUTHEAST, point))
1330  myPad.edge(SOUTHEAST) = point;
1331  // std::cout << " Apres " << std::endl;
1332  // std::cout << myPad<< std::endl;
1333  }
1334 }
1335 
1336 void EcalHitMaker::cracksPads(std::vector<neighbour>& cracks, unsigned iq) {
1337  // std::cout << " myPad " << &myPad << std::endl;
1338  unsigned ncracks = cracks.size();
1339  CrystalPad& myPad = padsatdepth_[iq];
1340  for (unsigned ic = 0; ic < ncracks; ++ic) {
1341  // std::vector<CLHEP::Hep2Vector> mycorners;
1342  // mycorners.reserve(4);
1343  switch (cracks[ic].first) {
1344  case NORTH: {
1345  mycorners[0] = (padsatdepth_[cracks[ic].second].edge(SOUTHWEST));
1346  mycorners[1] = (padsatdepth_[cracks[ic].second].edge(SOUTHEAST));
1347  mycorners[2] = (myPad.edge(NORTHEAST));
1348  mycorners[3] = (myPad.edge(NORTHWEST));
1349  } break;
1350  case SOUTH: {
1351  mycorners[0] = (myPad.edge(SOUTHWEST));
1352  mycorners[1] = (myPad.edge(SOUTHEAST));
1353  mycorners[2] = (padsatdepth_[cracks[ic].second].edge(NORTHEAST));
1354  mycorners[3] = (padsatdepth_[cracks[ic].second].edge(NORTHWEST));
1355  } break;
1356  case EAST: {
1357  mycorners[0] = (myPad.edge(NORTHEAST));
1358  mycorners[1] = (padsatdepth_[cracks[ic].second].edge(NORTHWEST));
1359  mycorners[2] = (padsatdepth_[cracks[ic].second].edge(SOUTHWEST));
1360  mycorners[3] = (myPad.edge(SOUTHEAST));
1361  } break;
1362  case WEST: {
1363  mycorners[0] = (padsatdepth_[cracks[ic].second].edge(NORTHEAST));
1364  mycorners[1] = (myPad.edge(NORTHWEST));
1365  mycorners[2] = (myPad.edge(SOUTHWEST));
1366  mycorners[3] = (padsatdepth_[cracks[ic].second].edge(SOUTHEAST));
1367  } break;
1368  default: {
1369  }
1370  }
1371  CrystalPad crackpad(ic, mycorners);
1372  // to be tuned. A simpleconfigurable should be used
1374  crackpadsatdepth_.push_back(crackpad);
1375  }
1376  // std::cout << " Finished cracksPads " << std::endl;
1377 }
1378 
1379 bool EcalHitMaker::inside3D(const std::vector<XYZPoint>& corners, const XYZPoint& p) const {
1380  // corners and p are in the same plane
1381  // p is inside "corners" if the four crossproducts (corners[i]xcorners[i+1])
1382  // are in the same direction
1383 
1384  XYZVector crossproduct(0., 0., 0.), previouscrossproduct(0., 0., 0.);
1385 
1386  for (unsigned ip = 0; ip < 4; ++ip) {
1387  crossproduct = (corners[ip] - p).Cross(corners[(ip + 1) % 4] - p);
1388  if (ip == 0)
1389  previouscrossproduct = crossproduct;
1390  else if (crossproduct.Dot(previouscrossproduct) < 0.)
1391  return false;
1392  }
1393 
1394  return true;
1395 }
size
Write out results.
const CaloSubdetectorGeometry * getEcalGeometry(int subdetn) const
Definition: Calorimeter.cc:132
XYZNormal normal_
Definition: EcalHitMaker.h:214
void ecalCellLine(const XYZPoint &, const XYZPoint &, std::vector< CaloPoint > &cp)
const DetId & getDetId() const
get the DetId
Definition: Crystal.h:46
double pulledPadProbability_
Definition: EcalHitMaker.h:264
bool addHit(double r, double phi, unsigned layer=0) override
void buildCrystal(const DetId &id, Crystal &) const
bool detailedShowerTail_
Definition: EcalHitMaker.h:250
const RawParticle & vfcalEntrance() const
The particle at VFCAL entrance.
Definition: FSimTrack.h:149
unsigned ny_
Definition: EcalHitMaker.h:221
CrystalWindowMap * myCrystalWindowMap_
Definition: EcalHitMaker.h:233
void convertIntegerCoordinates(double x, double y, unsigned &ix, unsigned &iy) const
DetId getClosestCell(const XYZPoint &point, bool ecal, bool central) const
std::map< DetId, unsigned > DetIdMap_
Definition: EcalHitMaker.h:231
std::vector< CrystalPad > crackpadsatdepth_
Definition: EcalHitMaker.h:282
const RawParticle & hcalEntrance() const
The particle at HCAL entrance.
Definition: FSimTrack.h:146
static CaloDirection add2d(const CaloDirection &dir1, const CaloDirection &dir2)
const PreshowerLayer1Properties * layer1Properties(int onLayer1) const
Preshower Layer1 properties.
Definition: Calorimeter.cc:103
static const char * normal
Definition: DMRtrends.cc:35
const RawParticle & layer2Entrance() const
The particle at Preshower Layer 2.
Definition: FSimTrack.h:140
EcalHitMaker(CaloGeometryHelper *calo, const XYZPoint &ecalentrance, const DetId &cell, int onEcal, unsigned size, unsigned showertype, const RandomEngineAndDistribution *engine)
Definition: EcalHitMaker.cc:33
bool getCrystalWindow(unsigned, std::vector< unsigned > &) const
get the ordered list of the crystals around the crystal given as a first argument ...
std::map< CaloHitID, float > hitMap_
Definition: CaloHitMaker.h:61
static CaloDirection oppositeSide(const CaloDirection &side)
void reorganizePads()
ROOT::Math::Plane3D::Vector Vector
Definition: EcalHitMaker.cc:29
const RawParticle & ecalEntrance() const
The particle at ECAL entrance.
Definition: FSimTrack.h:143
bool unbalancedDirection(const std::vector< neighbour > &dirs, unsigned &unb, unsigned &dir1, unsigned &dir2)
std::vector< CrystalPad > padsatdepth_
Definition: EcalHitMaker.h:281
Sin< T >::type sin(const T &t)
Definition: Sin.h:22
const PreshowerLayer2Properties * layer2Properties(int onLayer2) const
Preshower Layer2 properties.
Definition: Calorimeter.cc:110
void getWindow(const DetId &pivot, int s1, int s2, std::vector< DetId > &) const
math::XYZVector XYZPoint
Definition: CaloHitMaker.h:23
double L0HCAL_
Definition: EcalHitMaker.h:204
Plane3D plan_
Definition: EcalHitMaker.h:261
std::vector< CLHEP::Hep2Vector > mycorners
Definition: EcalHitMaker.h:287
#define M_PI_2
const RandomEngineAndDistribution * random
Definition: EcalHitMaker.h:290
static unsigned oppositeDirection(unsigned iside)
CLHEP::Hep2Vector & edge(unsigned iside, int n)
access to the corners in direction iside; n=0,1
Definition: CrystalPad.cc:222
int onHcal() const
Definition: FSimTrack.h:116
const EcalEndcapGeometry * getEcalEndcapGeometry() const
Definition: Calorimeter.h:52
void prepareCrystalNumberArray()
const FSimVertex vertex() const
Origin vertex.
double currentdepth_
Definition: EcalHitMaker.h:252
static unsigned neighbourDirection(const CaloDirection &side)
unsigned int -> Direction for the neighbours
bool simulatePreshower_
Definition: EcalHitMaker.h:256
unsigned ncrystals_
Definition: EcalHitMaker.h:219
double X0HCAL_
Definition: EcalHitMaker.h:199
const CaloGeometryHelper * myCalorimeter
Definition: CaloHitMaker.h:44
ROOT::Math::Transform3DPJ Transform3DR
Definition: EcalHitMaker.cc:31
double thickness(const double eta) const override
bool inside3D(const std::vector< XYZPoint > &, const XYZPoint &p) const
bool pulled(const XYZPoint &origin, const XYZNormal &normal, XYZPoint &fPoint) const
unsigned etasize_
Definition: EcalHitMaker.h:239
int hashedIndex(int ieta, int iphi)
Definition: EcalPyUtils.cc:36
bool truncatedGrid_
Definition: EcalHitMaker.h:242
unsigned fastInsideCell(const CLHEP::Hep2Vector &point, double &sp, bool debug=false)
bool configuredGeometry_
Definition: EcalHitMaker.h:218
double crackPadProbability_
Definition: EcalHitMaker.h:266
const XYZVector & getFirstEdge() const
Direction of the first edge.
Definition: Crystal.h:42
bool addHitDepth(double r, double phi, double depth=-1)
double L0PS2EE_
Definition: EcalHitMaker.h:202
double eta() const
Definition: RawParticle.h:279
const std::map< CaloHitID, float > & getHits() override
double radiusCorrectionFactor_
Definition: EcalHitMaker.h:246
T sqrt(T t)
Definition: SSEVec.h:19
double radiusFactor_
Definition: EcalHitMaker.h:248
double L0ECAL_
Definition: EcalHitMaker.h:203
void setTrackParameters(const XYZNormal &normal, double X0depthoffset, const FSimTrack &theTrack)
Cos< T >::type cos(const T &t)
Definition: Cos.h:22
double X0EHGAP_
Definition: EcalHitMaker.h:198
const FSimTrack * myTrack_
Definition: EcalHitMaker.h:271
double ecalTotalX0() const
in the ECAL
Definition: EcalHitMaker.h:67
bool move(DetId &cell, const CaloDirection &dir, bool fast=true) const
static Histos * instance()
Definition: Histos.cc:15
Tan< T >::type tan(const T &t)
Definition: Tan.h:22
void cracksPads(std::vector< neighbour > &cracks, unsigned iq)
int onLayer2() const
Definition: FSimTrack.h:106
double totalL0_
Definition: EcalHitMaker.h:192
double L0EHGAP_
Definition: EcalHitMaker.h:205
static XYZPoint intersect(const Plane3D &p, const XYZPoint &a, const XYZPoint &b, double &t, bool segment, bool debug=false)
Definition: CaloHitMaker.cc:41
int onLayer1() const
Definition: FSimTrack.h:101
std::vector< CaloPoint > intersections_
Definition: EcalHitMaker.h:274
unsigned phisize_
Definition: EcalHitMaker.h:240
double L0length() const
length of the segment (in L9)
Definition: CaloSegment.h:47
static CaloDirection Side(unsigned i)
unsigned int -> Side conversion
int onVFcal() const
Definition: FSimTrack.h:121
virtual std::shared_ptr< const CaloCellGeometry > getGeometry(const DetId &id) const
Get the cell geometry of a given detector id. Should return false if not found.
int onEcal() const
Definition: FSimTrack.h:111
ii
Definition: cuy.py:589
#define M_PI
double outsideWindowEnergy_
Definition: EcalHitMaker.h:209
void gapsLifting(std::vector< neighbour > &gaps, unsigned iq)
CLHEP::Hep2Vector & correspondingEdge(neighbour &myneighbour, CaloDirection dir2)
ROOT::Math::Plane3D Plane3D
Definition: EcalHitMaker.h:29
This class is used to determine if a point lies in the segment.
Definition: CaloSegment.h:87
XYZVector Vect() const
the momentum threevector
Definition: RawParticle.h:323
std::pair< CaloDirection, unsigned > neighbour
Definition: EcalHitMaker.h:168
Definition: DetId.h:17
unsigned ncrackpadsatdepth_
Definition: EcalHitMaker.h:259
std::vector< XYZPoint > corners
Definition: EcalHitMaker.h:288
#define debug
Definition: HDRShower.cc:19
double thickness(double eta) const override
bool borderCrossing(const DetId &, const DetId &) const
double X0PS2EE_
Definition: EcalHitMaker.h:196
T mag2() const
The vector magnitude squared. Equivalent to vec.dot(vec)
double bfactor_
Definition: EcalHitMaker.h:254
void preshowerCellLine(std::vector< CaloPoint > &cp) const
Crystal pivot_
Definition: EcalHitMaker.h:212
Detector
Definition: DetId.h:24
ROOT::Math::Plane3D Plane3D
Definition: CaloHitMaker.h:24
const math::XYZTLorentzVector & position() const
Temporary (until CMSSW moves to Mathcore) - No ! Actually very useful.
Definition: FSimVertex.h:48
double length() const
length of the segment (in cm)
Definition: CaloSegment.h:43
void configureGeometry()
double interactionLength
Definition: CaloHitMaker.h:47
double b
Definition: hdecay.h:120
XYZPoint EcalEntrance_
Definition: EcalHitMaker.h:213
double X0ECAL_
Definition: EcalHitMaker.h:197
bool getPads(double depth, bool inCm=false)
void cellLine(std::vector< CaloPoint > &cp)
int ecalFirstSegment_
Definition: EcalHitMaker.h:236
std::vector< std::vector< unsigned > > myCrystalNumberArray_
Definition: EcalHitMaker.h:188
std::vector< float > hits_
Definition: EcalHitMaker.h:226
double moliereRadius
Definition: CaloHitMaker.h:46
std::vector< Crystal > regionOfInterest_
Definition: EcalHitMaker.h:225
double magneticField() const
void buildSegments(const std::vector< CaloPoint > &cp)
double X0length() const
length of the segment (in X0)
Definition: CaloSegment.h:45
void hcalCellLine(std::vector< CaloPoint > &cp) const
Structure Point Contains parameters of Gaussian fits to DMRs.
double a
Definition: hdecay.h:121
~EcalHitMaker() override
float x
math::XYZVector XYZVector
Definition: CaloHitMaker.h:22
void setSurvivalProbability(double val)
Definition: CrystalPad.h:64
void buildGeometry()
double X0depthoffset_
Definition: EcalHitMaker.h:193
std::vector< bool > validPads_
Definition: EcalHitMaker.h:228
std::vector< DetId > CellsWindow_
Definition: EcalHitMaker.h:224
CaloDirection
Codes the local directions in the cell lattice.
Definition: CaloDirection.h:9
virtual double thickness(double eta) const =0
Thickness (in cm) of the homegeneous material as a function of rapidity.
double flatShoot(double xmin=0.0, double xmax=1.0) const
ROOT::Math::Plane3D::Point Point
Definition: EcalHitMaker.cc:30
bool hitmaphasbeencalculated_
Definition: EcalHitMaker.h:284
unsigned npadsatdepth_
Definition: EcalHitMaker.h:260
const RawParticle & layer1Entrance() const
The particle at Preshower Layer 1.
Definition: FSimTrack.h:137
static constexpr float d1
Definition: TkAlStyle.h:43
const HCALProperties * hcalProperties(int onHcal) const
HCAL properties.
Definition: Calorimeter.cc:88
tmp
align.sh
Definition: createJobs.py:716
math::XYZVector XYZNormal
Definition: EcalHitMaker.h:28
Geom::Theta< T > theta() const
double rearleakage_
Definition: EcalHitMaker.h:208
double spotEnergy
Definition: CaloHitMaker.h:48
*vegas h *****************************************************used in the default bin number in original ***version of VEGAS is ***a higher bin number might help to derive a more precise ***grade subtle point
Definition: invegas.h:5
const XYZTLorentzVector & vertex() const
the vertex fourvector
Definition: RawParticle.h:320
bool diagonalEdge(unsigned myPad, CaloDirection dir, CLHEP::Hep2Vector &point)
double totalX0_
Definition: EcalHitMaker.h:191
std::vector< CaloSegment > segments_
Definition: EcalHitMaker.h:276
unsigned nx_
Definition: EcalHitMaker.h:221
T angle(T x1, T y1, T z1, T x2, T y2, T z2)
Definition: angle.h:11