CMS 3D CMS Logo

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