File indexing completed on 2024-09-07 04:36:17
0001 #include "DataFormats/DetId/interface/DetId.h"
0002 #include "DataFormats/EcalDetId/interface/EcalSubdetector.h"
0003 #include "DataFormats/EcalDetId/interface/EBDetId.h"
0004 #include "DataFormats/EcalDetId/interface/EEDetId.h"
0005
0006
0007
0008
0009
0010 #include "Geometry/CaloGeometry/interface/CaloSubdetectorGeometry.h"
0011 #include "FastSimulation/CaloHitMakers/interface/EcalHitMaker.h"
0012 #include "FastSimulation/CaloGeometryTools/interface/CaloGeometryHelper.h"
0013 #include "FastSimulation/CaloGeometryTools/interface/CrystalWindowMap.h"
0014 #include "FastSimulation/CaloGeometryTools/interface/CaloDirectionOperations.h"
0015 #include "FastSimulation/Event/interface/FSimVertex.h"
0016 #include "FastSimulation/Event/interface/FSimTrack.h"
0017 #include "FastSimulation/CalorimeterProperties/interface/PreshowerLayer1Properties.h"
0018 #include "FastSimulation/CalorimeterProperties/interface/PreshowerLayer2Properties.h"
0019 #include "FastSimulation/CalorimeterProperties/interface/HCALProperties.h"
0020 #include "FastSimulation/Utilities/interface/RandomEngineAndDistribution.h"
0021
0022
0023
0024 #include "FastSimulation/CaloGeometryTools/interface/Transform3DPJ.h"
0025
0026 #include <algorithm>
0027 #include <cmath>
0028
0029 typedef ROOT::Math::Plane3D::Vector Vector;
0030 typedef ROOT::Math::Plane3D::Point Point;
0031 typedef ROOT::Math::Transform3DPJ Transform3DR;
0032
0033 EcalHitMaker::EcalHitMaker(CaloGeometryHelper* theCalo,
0034 const XYZPoint& ecalentrance,
0035 const DetId& cell,
0036 int onEcal,
0037 unsigned size,
0038 unsigned showertype,
0039 const RandomEngineAndDistribution* engine)
0040 : CaloHitMaker(theCalo, DetId::Ecal, ((onEcal == 1) ? EcalBarrel : EcalEndcap), onEcal, showertype),
0041 EcalEntrance_(ecalentrance),
0042 onEcal_(onEcal),
0043 myTrack_(nullptr),
0044 random(engine) {
0045 #ifdef FAMOSDEBUG
0046 myHistos = Histos::instance();
0047 #endif
0048
0049 simulatePreshower_ = true;
0050 X0depthoffset_ = 0.;
0051 X0PS1_ = 0.;
0052 X0PS2_ = 0.;
0053 X0PS2EE_ = 0.;
0054 X0ECAL_ = 0.;
0055 X0EHGAP_ = 0.;
0056 X0HCAL_ = 0.;
0057 L0PS1_ = 0.;
0058 L0PS2_ = 0.;
0059 L0PS2EE_ = 0.;
0060 L0ECAL_ = 0.;
0061 L0EHGAP_ = 0.;
0062 L0HCAL_ = 0.;
0063 maxX0_ = 0.;
0064 totalX0_ = 0;
0065 totalL0_ = 0.;
0066 pulledPadProbability_ = 1.;
0067 outsideWindowEnergy_ = 0.;
0068 rearleakage_ = 0.;
0069 bfactor_ = 1.;
0070 ncrystals_ = 0;
0071
0072 doreorg_ = !showertype;
0073
0074 hitmaphasbeencalculated_ = false;
0075
0076 if (onEcal)
0077 myCalorimeter->buildCrystal(cell, pivot_);
0078 else
0079 pivot_ = Crystal();
0080 central_ = onEcal == 1;
0081 ecalFirstSegment_ = -1;
0082
0083 myCrystalWindowMap_ = nullptr;
0084
0085
0086 if (!onEcal)
0087 return;
0088
0089
0090 etasize_ = size;
0091 phisize_ = size;
0092
0093
0094
0095 myCalorimeter->getWindow(pivot_.getDetId(), size, size, CellsWindow_);
0096
0097 buildGeometry();
0098
0099
0100 truncatedGrid_ = CellsWindow_.size() != (etasize_ * phisize_);
0101
0102
0103 mycorners.resize(4);
0104 corners.resize(4);
0105
0106 #ifdef DEBUGGW
0107 myHistos->fill("h10", EcalEntrance_.eta(), CellsWindow_.size());
0108 if (onEcal == 2) {
0109 myHistos->fill("h20", EcalEntrance_.perp(), CellsWindow_.size());
0110 if (EcalEntrance_.perp() > 70 && EcalEntrance_.perp() < 80 && CellsWindow_.size() < 35) {
0111 std::cout << " Truncated grid " << CellsWindow_.size() << " " << EcalEntrance_.perp() << std::endl;
0112 std::cout << " Pivot "
0113 << myCalorimeter->getEcalEndcapGeometry()->getGeometry(pivot_.getDetId())->getPosition().perp();
0114 std::cout << EEDetId(pivot_.getDetId()) << std::endl;
0115
0116 std::cout << " Test getClosestCell " << EcalEntrance_ << std::endl;
0117 DetId testcell = myCalorimeter->getClosestCell(EcalEntrance_, true, false);
0118 std::cout << " Result " << EEDetId(testcell) << std::endl;
0119 std::cout << " Position " << myCalorimeter->getEcalEndcapGeometry()->getGeometry(testcell)->getPosition()
0120 << std::endl;
0121 }
0122 }
0123
0124 #endif
0125 }
0126
0127 EcalHitMaker::~EcalHitMaker() {
0128 if (myCrystalWindowMap_ != nullptr) {
0129 delete myCrystalWindowMap_;
0130 }
0131 }
0132
0133 bool EcalHitMaker::addHitDepth(double r, double phi, double depth) {
0134
0135
0136 depth += X0depthoffset_;
0137 double sp(1.);
0138 r *= radiusFactor_;
0139 CLHEP::Hep2Vector point(r * std::cos(phi), r * std::sin(phi));
0140
0141 unsigned xtal = fastInsideCell(point, sp);
0142
0143
0144
0145
0146
0147
0148
0149 if (xtal < 1000) {
0150
0151
0152 if (regionOfInterest_[xtal].getX0Back() > depth) {
0153 hits_[xtal] += spotEnergy;
0154
0155 return true;
0156 } else {
0157 rearleakage_ += spotEnergy;
0158 }
0159 } else {
0160
0161
0162
0163
0164 }
0165
0166 outsideWindowEnergy_ += spotEnergy;
0167 return false;
0168 }
0169
0170
0171
0172
0173
0174
0175
0176
0177
0178
0179
0180
0181
0182
0183
0184 bool EcalHitMaker::addHit(double r, double phi, unsigned layer) {
0185
0186
0187 double sp(1.);
0188
0189 r *= radiusFactor_;
0190 CLHEP::Hep2Vector point(r * std::cos(phi), r * std::sin(phi));
0191
0192
0193 unsigned xtal = fastInsideCell(point, sp);
0194
0195 if (xtal < 1000) {
0196 if (sp == 1.)
0197 hits_[xtal] += spotEnergy;
0198 else
0199 hits_[xtal] += (random->flatShoot() < sp) * spotEnergy;
0200 return true;
0201 }
0202
0203 outsideWindowEnergy_ += spotEnergy;
0204
0205
0206
0207
0208
0209
0210
0211 return false;
0212 }
0213
0214
0215
0216
0217
0218
0219
0220
0221
0222
0223
0224
0225
0226
0227
0228
0229 unsigned EcalHitMaker::fastInsideCell(const CLHEP::Hep2Vector& point, double& sp, bool debug) {
0230
0231 bool found = false;
0232
0233 unsigned d1, d2;
0234 convertIntegerCoordinates(point.x(), point.y(), d1, d2);
0235
0236 if (d1 >= nx_ || d2 >= ny_) {
0237
0238 return 9999;
0239 }
0240 unsigned cell = myCrystalNumberArray_[d1][d2];
0241
0242
0243 if (validPads_[cell] && padsatdepth_[cell].inside(point)) {
0244
0245 sp = padsatdepth_[cell].survivalProbability();
0246 return cell;
0247 }
0248
0249
0250 bool status(true);
0251 const std::vector<unsigned>& localCellVector(myCrystalWindowMap_->getCrystalWindow(cell, status));
0252 if (status) {
0253 unsigned size = localCellVector.size();
0254
0255
0256
0257
0258
0259
0260
0261
0262 for (unsigned ic = 0; ic < 8 && ic < size; ++ic) {
0263 unsigned iq = localCellVector[ic];
0264
0265
0266
0267 if (validPads_[iq] && padsatdepth_[iq].inside(point)) {
0268
0269
0270 sp = padsatdepth_[iq].survivalProbability();
0271
0272
0273 return iq;
0274 }
0275
0276
0277 }
0278 }
0279 if (debug)
0280 std::cout << " not found in a quad, let's check the " << ncrackpadsatdepth_ << " cracks " << std::endl;
0281
0282
0283
0284 unsigned iquad = 0;
0285 unsigned iquadinside = 999;
0286 while (iquad < ncrackpadsatdepth_ && !found) {
0287
0288 if (crackpadsatdepth_[iquad].inside(point)) {
0289 iquadinside = iquad;
0290 found = true;
0291 sp = crackpadsatdepth_[iquad].survivalProbability();
0292 }
0293 ++iquad;
0294 }
0295
0296 if (!found && debug)
0297 std::cout << " Not found in the cracks " << std::endl;
0298 return (found) ? crackpadsatdepth_[iquadinside].getNumber() : 9999;
0299 }
0300
0301 void EcalHitMaker::setTrackParameters(const XYZNormal& normal, double X0depthoffset, const FSimTrack& theTrack) {
0302
0303
0304 intersections_.clear();
0305
0306 intersections_.reserve(50);
0307 myTrack_ = &theTrack;
0308 normal_ = normal.Unit();
0309 X0depthoffset_ = X0depthoffset;
0310 cellLine(intersections_);
0311 buildSegments(intersections_);
0312
0313
0314
0315
0316
0317
0318
0319 if (EMSHOWER && onEcal_ && ecalTotalX0() > 0.) {
0320
0321 for (unsigned ic = 0; ic < ncrystals_; ++ic) {
0322 for (unsigned idir = 0; idir < 4; ++idir) {
0323 XYZVector norm = regionOfInterest_[ic].exitingNormal(CaloDirectionOperations::Side(idir));
0324 regionOfInterest_[ic].crystalNeighbour(idir).setToBeGlued((norm.Dot(normal_) < 0.));
0325 }
0326
0327
0328 if (EMSHOWER) {
0329 XYZVector dir = regionOfInterest_[ic].getBackCenter() - segments_[ecalFirstSegment_].entrance();
0330 double dist = dir.Dot(normal_);
0331 double absciss = dist + segments_[ecalFirstSegment_].sEntrance();
0332 std::vector<CaloSegment>::const_iterator segiterator;
0333
0334
0335
0336
0337 segiterator = find_if(segments_.begin(), segments_.end(), CaloSegment::inSegment(absciss));
0338
0339 if (segiterator == segments_.end()) {
0340
0341
0342 regionOfInterest_[ic].setX0Back(9999);
0343 } else {
0344 DetId::Detector det(segiterator->whichDetector());
0345 if (det != DetId::Ecal) {
0346 regionOfInterest_[ic].setX0Back(9999);
0347 } else {
0348 double x0 = segiterator->x0FromCm(dist);
0349 if (x0 < maxX0_)
0350 maxX0_ = x0;
0351 regionOfInterest_[ic].setX0Back(x0);
0352 }
0353 }
0354
0355
0356
0357
0358
0359
0360
0361
0362 }
0363 }
0364
0365 }
0366
0367 }
0368
0369 void EcalHitMaker::cellLine(std::vector<CaloPoint>& cp) {
0370 cp.clear();
0371
0372
0373 if (!central_ && onEcal_ && simulatePreshower_)
0374 preshowerCellLine(cp);
0375 if (onEcal_)
0376 ecalCellLine(EcalEntrance_, EcalEntrance_ + normal_, cp);
0377
0378
0379 XYZPoint vertex(myTrack_->vertex().position().Vect());
0380
0381
0382 XYZVector dir(0., 0., 0.);
0383 if (myTrack_->onLayer1()) {
0384 vertex = (myTrack_->layer1Entrance().vertex()).Vect();
0385 dir = myTrack_->layer1Entrance().Vect().Unit();
0386 } else if (myTrack_->onLayer2()) {
0387 vertex = (myTrack_->layer2Entrance().vertex()).Vect();
0388 dir = myTrack_->layer2Entrance().Vect().Unit();
0389 } else if (myTrack_->onEcal()) {
0390 vertex = (myTrack_->ecalEntrance().vertex()).Vect();
0391 dir = myTrack_->ecalEntrance().Vect().Unit();
0392 } else if (myTrack_->onHcal()) {
0393 vertex = (myTrack_->hcalEntrance().vertex()).Vect();
0394 dir = myTrack_->hcalEntrance().Vect().Unit();
0395 } else if (myTrack_->onVFcal() == 2) {
0396 vertex = (myTrack_->vfcalEntrance().vertex()).Vect();
0397 dir = myTrack_->vfcalEntrance().Vect().Unit();
0398 } else {
0399 std::cout << " Problem with the grid " << std::endl;
0400 }
0401
0402
0403 vertex -= 5. * dir;
0404 CaloPoint::DistanceToVertex myDistance(vertex);
0405 sort(cp.begin(), cp.end(), myDistance);
0406
0407
0408
0409 hcalCellLine(cp);
0410
0411
0412
0413
0414
0415
0416
0417
0418 }
0419
0420 void EcalHitMaker::preshowerCellLine(std::vector<CaloPoint>& cp) const {
0421
0422
0423
0424
0425
0426 if (myTrack_->onLayer1()) {
0427 XYZPoint point1 = (myTrack_->layer1Entrance().vertex()).Vect();
0428 double phys_eta = myTrack_->layer1Entrance().eta();
0429 double cmthickness = myCalorimeter->layer1Properties(1)->thickness(phys_eta);
0430
0431 if (cmthickness > 0) {
0432 XYZVector dir = myTrack_->layer1Entrance().Vect().Unit();
0433 XYZPoint point2 = point1 + dir * cmthickness;
0434
0435 CaloPoint cp1(DetId::Ecal, EcalPreshower, 1, point1);
0436 CaloPoint cp2(DetId::Ecal, EcalPreshower, 1, point2);
0437 cp.push_back(cp1);
0438 cp.push_back(cp2);
0439 } else {
0440
0441 }
0442 }
0443
0444
0445 if (myTrack_->onLayer2()) {
0446 XYZPoint point1 = (myTrack_->layer2Entrance().vertex()).Vect();
0447 double phys_eta = myTrack_->layer2Entrance().eta();
0448 double cmthickness = myCalorimeter->layer2Properties(1)->thickness(phys_eta);
0449 if (cmthickness > 0) {
0450 XYZVector dir = myTrack_->layer2Entrance().Vect().Unit();
0451 XYZPoint point2 = point1 + dir * cmthickness;
0452
0453 CaloPoint cp1(DetId::Ecal, EcalPreshower, 2, point1);
0454 CaloPoint cp2(DetId::Ecal, EcalPreshower, 2, point2);
0455
0456 cp.push_back(cp1);
0457 cp.push_back(cp2);
0458 } else {
0459
0460 }
0461 }
0462
0463 }
0464
0465 void EcalHitMaker::hcalCellLine(std::vector<CaloPoint>& cp) const {
0466
0467
0468 int onHcal = myTrack_->onHcal();
0469
0470 if (onHcal <= 2 && onHcal > 0) {
0471 XYZPoint point1 = (myTrack_->hcalEntrance().vertex()).Vect();
0472
0473 double eta = point1.eta();
0474
0475 double thickness = myCalorimeter->hcalProperties(onHcal)->thickness(eta);
0476 cp.push_back(CaloPoint(DetId::Hcal, point1));
0477 XYZVector dir = myTrack_->hcalEntrance().Vect().Unit();
0478 XYZPoint point2 = point1 + dir * thickness;
0479
0480 cp.push_back(CaloPoint(DetId::Hcal, point2));
0481 }
0482 int onVFcal = myTrack_->onVFcal();
0483 if (onVFcal == 2) {
0484 XYZPoint point1 = (myTrack_->vfcalEntrance().vertex()).Vect();
0485 double eta = point1.eta();
0486
0487 double thickness = myCalorimeter->hcalProperties(3)->thickness(eta);
0488 cp.push_back(CaloPoint(DetId::Hcal, point1));
0489 XYZVector dir = myTrack_->vfcalEntrance().Vect().Unit();
0490 if (thickness > 0) {
0491 XYZPoint point2 = point1 + dir * thickness;
0492 cp.push_back(CaloPoint(DetId::Hcal, point2));
0493 }
0494 }
0495 }
0496
0497 void EcalHitMaker::ecalCellLine(const XYZPoint& a, const XYZPoint& b, std::vector<CaloPoint>& cp) {
0498
0499
0500 unsigned ic = 0;
0501 double t;
0502 XYZPoint xp;
0503 DetId c_entrance, c_exit;
0504 bool entrancefound(false), exitfound(false);
0505
0506
0507
0508
0509 double angle = std::acos(normal_.Dot(regionOfInterest_[0].getAxis().Unit()));
0510
0511
0512 double backdistance = std::sqrt(regionOfInterest_[0].getAxis().mag2()) * std::tan(angle);
0513
0514
0515
0516 unsigned ncrystals = (unsigned)(backdistance * 0.45);
0517 unsigned highlim = (ncrystals + 4);
0518 highlim *= highlim;
0519 if (highlim > ncrystals_)
0520 highlim = ncrystals_;
0521
0522
0523
0524 while (ic < ncrystals_ && (ic < highlim || !exitfound)) {
0525
0526
0527 {
0528 const Plane3D& plan = regionOfInterest_[ic].getFrontPlane();
0529
0530
0531 xp = intersect(plan, a, b, t, false);
0532 regionOfInterest_[ic].getFrontSide(corners);
0533
0534
0535 if (inside3D(corners, xp)) {
0536 cp.push_back(CaloPoint(regionOfInterest_[ic].getDetId(), UP, xp));
0537 entrancefound = true;
0538 c_entrance = regionOfInterest_[ic].getDetId();
0539
0540 }
0541 }
0542
0543
0544
0545 {
0546 const Plane3D& plan = regionOfInterest_[ic].getBackPlane();
0547
0548
0549 xp = intersect(plan, a, b, t, false);
0550 regionOfInterest_[ic].getBackSide(corners);
0551
0552
0553 if (inside3D(corners, xp)) {
0554 cp.push_back(CaloPoint(regionOfInterest_[ic].getDetId(), DOWN, xp));
0555 exitfound = true;
0556 c_exit = regionOfInterest_[ic].getDetId();
0557
0558
0559 }
0560 }
0561
0562 if (entrancefound && exitfound && c_entrance == c_exit)
0563 return;
0564
0565 for (unsigned iside = 0; iside < 4; ++iside) {
0566 const Plane3D& plan = regionOfInterest_[ic].getLateralPlane(iside);
0567 xp = intersect(plan, a, b, t, false);
0568
0569
0570 regionOfInterest_[ic].getLateralSide(iside, corners);
0571
0572
0573 if (inside3D(corners, xp)) {
0574 cp.push_back(CaloPoint(regionOfInterest_[ic].getDetId(), CaloDirectionOperations::Side(iside), xp));
0575
0576 }
0577 }
0578
0579 ++ic;
0580 }
0581 }
0582
0583 void EcalHitMaker::buildSegments(const std::vector<CaloPoint>& cp) {
0584
0585
0586 unsigned size = cp.size();
0587 if (size % 2 != 0) {
0588
0589 return;
0590 }
0591
0592 unsigned nsegments = size / 2;
0593 segments_.reserve(nsegments);
0594 if (size == 0)
0595 return;
0596
0597 double s = 0.;
0598 double sX0 = 0.;
0599 double sL0 = 0.;
0600
0601 #ifdef DEBUGCELLLINE
0602 unsigned ncrossedxtals = 0;
0603 #endif
0604 unsigned is = 0;
0605 while (is < nsegments) {
0606 if (cp[2 * is].getDetId() != cp[2 * is + 1].getDetId() && cp[2 * is].whichDetector() != DetId::Hcal &&
0607 cp[2 * is + 1].whichDetector() != DetId::Hcal) {
0608
0609
0610
0611
0612 ++is;
0613 continue;
0614 }
0615
0616
0617
0618
0619 if (cp[2 * is].whichDetector() == DetId::Ecal && cp[2 * is].whichSubDetector() == EcalPreshower &&
0620 cp[2 * is].whichLayer() == 1) {
0621 if (cp[2 * is + 1].whichDetector() == DetId::Ecal && cp[2 * is + 1].whichSubDetector() == EcalPreshower &&
0622 cp[2 * is + 1].whichLayer() == 1) {
0623 CaloSegment preshsegment(cp[2 * is], cp[2 * is + 1], s, sX0, sL0, CaloSegment::PS, myCalorimeter);
0624 segments_.push_back(preshsegment);
0625
0626 s += preshsegment.length();
0627 sX0 += preshsegment.X0length();
0628 sL0 += preshsegment.L0length();
0629 X0PS1_ += preshsegment.X0length();
0630 L0PS1_ += preshsegment.L0length();
0631 } else {
0632 std::cout << " Strange segment between Preshower1 and " << cp[2 * is + 1].whichDetector();
0633 std::cout << std::endl;
0634 }
0635 ++is;
0636 continue;
0637 }
0638
0639
0640
0641 if (cp[2 * is].whichDetector() == DetId::Ecal && cp[2 * is].whichSubDetector() == EcalPreshower &&
0642 cp[2 * is].whichLayer() == 2) {
0643 if (cp[2 * is + 1].whichDetector() == DetId::Ecal && cp[2 * is + 1].whichSubDetector() == EcalPreshower &&
0644 cp[2 * is + 1].whichLayer() == 2) {
0645 CaloSegment preshsegment(cp[2 * is], cp[2 * is + 1], s, sX0, sL0, CaloSegment::PS, myCalorimeter);
0646 segments_.push_back(preshsegment);
0647
0648 s += preshsegment.length();
0649 sX0 += preshsegment.X0length();
0650 sL0 += preshsegment.L0length();
0651 X0PS2_ += preshsegment.X0length();
0652 L0PS2_ += preshsegment.L0length();
0653
0654
0655 if (is < (nsegments - 1) && cp[2 * is + 2].whichDetector() == DetId::Ecal &&
0656 cp[2 * is + 2].whichSubDetector() == EcalEndcap) {
0657 CaloSegment gapsef(cp[2 * is + 1], cp[2 * is + 2], s, sX0, sL0, CaloSegment::PSEEGAP, myCalorimeter);
0658 segments_.push_back(gapsef);
0659 s += gapsef.length();
0660 sX0 += gapsef.X0length();
0661 sL0 += gapsef.L0length();
0662 X0PS2EE_ += gapsef.X0length();
0663 L0PS2EE_ += gapsef.L0length();
0664
0665 }
0666 } else {
0667 std::cout << " Strange segment between Preshower2 and " << cp[2 * is + 1].whichDetector();
0668 std::cout << std::endl;
0669 }
0670 ++is;
0671 continue;
0672 }
0673
0674
0675
0676 if (cp[2 * is].whichDetector() == DetId::Ecal &&
0677 (cp[2 * is].whichSubDetector() == EcalBarrel || cp[2 * is].whichSubDetector() == EcalEndcap)) {
0678 if (cp[2 * is + 1].whichDetector() == DetId::Ecal &&
0679 (cp[2 * is + 1].whichSubDetector() == EcalBarrel || cp[2 * is + 1].whichSubDetector() == EcalEndcap)) {
0680 DetId cell2 = cp[2 * is + 1].getDetId();
0681
0682 if (ecalFirstSegment_ < 0)
0683 ecalFirstSegment_ = segments_.size();
0684
0685
0686 if (cp[2 * is].getDetId() == cell2) {
0687 CaloSegment segment(cp[2 * is], cp[2 * is + 1], s, sX0, sL0, CaloSegment::PbWO4, myCalorimeter);
0688 segments_.push_back(segment);
0689
0690 s += segment.length();
0691 sX0 += segment.X0length();
0692 sL0 += segment.L0length();
0693 X0ECAL_ += segment.X0length();
0694 L0ECAL_ += segment.L0length();
0695 #ifdef DEBUGCELLLINE
0696 ++ncrossedxtals;
0697 #endif
0698 ++is;
0699 } else {
0700 std::cout << " One more bug in the segment " << std::endl;
0701 ++is;
0702 }
0703
0704 if (is > 0 && is < nsegments) {
0705 DetId cell3 = cp[2 * is].getDetId();
0706 if (cp[2 * is].whichDetector() != DetId::Hcal) {
0707
0708 bool bordercrossing = myCalorimeter->borderCrossing(cell2, cell3);
0709 CaloSegment cracksegment(cp[2 * is - 1],
0710 cp[2 * is],
0711 s,
0712 sX0,
0713 sL0,
0714 (bordercrossing) ? CaloSegment::CRACK : CaloSegment::GAP,
0715 myCalorimeter);
0716 segments_.push_back(cracksegment);
0717 s += cracksegment.length();
0718 sX0 += cracksegment.X0length();
0719 sL0 += cracksegment.L0length();
0720 X0ECAL_ += cracksegment.X0length();
0721 L0ECAL_ += cracksegment.L0length();
0722
0723 } else {
0724
0725
0726 CaloSegment cracksegment(cp[2 * is - 1], cp[2 * is], s, sX0, sL0, CaloSegment::ECALHCALGAP, myCalorimeter);
0727 segments_.push_back(cracksegment);
0728 s += cracksegment.length();
0729 sX0 += cracksegment.X0length();
0730 sL0 += cracksegment.L0length();
0731 X0EHGAP_ += cracksegment.X0length();
0732 L0EHGAP_ += cracksegment.L0length();
0733 }
0734 }
0735 continue;
0736 } else {
0737 std::cout << " Strange segment between " << cp[2 * is].whichDetector();
0738 std::cout << " and " << cp[2 * is + 1].whichDetector() << std::endl;
0739 ++is;
0740 continue;
0741 }
0742 }
0743
0744
0745 if (cp[2 * is].whichDetector() == DetId::Hcal && cp[2 * is + 1].whichDetector() == DetId::Hcal) {
0746 CaloSegment segment(cp[2 * is], cp[2 * is + 1], s, sX0, sL0, CaloSegment::HCAL, myCalorimeter);
0747 segments_.push_back(segment);
0748 s += segment.length();
0749 sX0 += segment.X0length();
0750 sL0 += segment.L0length();
0751 X0HCAL_ += segment.X0length();
0752 L0HCAL_ += segment.L0length();
0753
0754 ++is;
0755 }
0756 }
0757
0758
0759
0760
0761
0762 totalX0_ = X0PS1_ + X0PS2_ + X0PS2EE_ + X0ECAL_ + X0EHGAP_ + X0HCAL_;
0763 totalL0_ = L0PS1_ + L0PS2_ + L0PS2EE_ + L0ECAL_ + L0EHGAP_ + L0HCAL_;
0764
0765
0766 #ifdef DEBUGCELLLINE
0767 myHistos->fill("h200", fabs(EcalEntrance_.eta()), X0ECAL_);
0768 myHistos->fill("h210", EcalEntrance_.phi(), X0ECAL_);
0769 if (X0ECAL_ < 20)
0770 myHistos->fill("h212", EcalEntrance_.phi(), X0ECAL_);
0771
0772
0773
0774
0775
0776
0777
0778 myHistos->fillByNumber("h30", ncrossedxtals, EcalEntrance_.eta(), X0ECAL_);
0779
0780 double zvertex = myTrack_->vertex().position().z();
0781
0782 myHistos->fill("h310", EcalEntrance_.eta(), X0ECAL_);
0783 if (X0ECAL_ < 22)
0784 myHistos->fill("h410", EcalEntrance_.phi());
0785 myHistos->fill("h400", zvertex, X0ECAL_);
0786 #endif
0787
0788 }
0789
0790 void EcalHitMaker::buildGeometry() {
0791 configuredGeometry_ = false;
0792 ncrystals_ = CellsWindow_.size();
0793
0794 padsatdepth_.resize(ncrystals_);
0795
0796
0797 ny_ = phisize_;
0798 nx_ = ncrystals_ / ny_;
0799 std::vector<unsigned> empty;
0800 empty.resize(ny_, 0);
0801 myCrystalNumberArray_.reserve((unsigned)nx_);
0802 for (unsigned inx = 0; inx < (unsigned)nx_; ++inx) {
0803 myCrystalNumberArray_.push_back(empty);
0804 }
0805
0806 hits_.resize(ncrystals_, 0.);
0807 regionOfInterest_.clear();
0808 regionOfInterest_.resize(ncrystals_);
0809 validPads_.resize(ncrystals_);
0810 for (unsigned ic = 0; ic < ncrystals_; ++ic) {
0811 myCalorimeter->buildCrystal(CellsWindow_[ic], regionOfInterest_[ic]);
0812 regionOfInterest_[ic].setNumber(ic);
0813 DetIdMap_.insert(std::pair<DetId, unsigned>(CellsWindow_[ic], ic));
0814 }
0815
0816
0817 myCrystalWindowMap_ = new CrystalWindowMap(myCalorimeter, regionOfInterest_);
0818 }
0819
0820
0821 bool EcalHitMaker::getPads(double depth, bool inCm) {
0822
0823
0824
0825
0826 if (EMSHOWER && !configuredGeometry_)
0827 configureGeometry();
0828
0829 radiusFactor_ = (EMSHOWER) ? moliereRadius * radiusCorrectionFactor_ : interactionLength;
0830 detailedShowerTail_ = false;
0831 if (EMSHOWER)
0832 currentdepth_ = depth + X0depthoffset_;
0833 else
0834 currentdepth_ = depth;
0835
0836
0837
0838
0839
0840
0841
0842
0843
0844 ncrackpadsatdepth_ = 0;
0845
0846 xmin_ = ymin_ = 999;
0847 xmax_ = ymax_ = -999;
0848 double locxmin, locxmax, locymin, locymax;
0849
0850
0851 std::vector<CaloSegment>::const_iterator segiterator;
0852
0853
0854 if (inCm)
0855 {
0856 segiterator = find_if(segments_.begin(), segments_.end(), CaloSegment::inSegment(currentdepth_));
0857 } else {
0858
0859 if (EMSHOWER)
0860 segiterator = find_if(segments_.begin(), segments_.end(), CaloSegment::inX0Segment(currentdepth_));
0861
0862
0863 if (HADSHOWER)
0864 segiterator = find_if(segments_.begin(), segments_.end(), CaloSegment::inL0Segment(currentdepth_));
0865 }
0866 if (segiterator == segments_.end()) {
0867 std::cout << " FamosGrid: Could not go at such depth " << depth << std::endl;
0868 std::cout << " EMSHOWER " << EMSHOWER << std::endl;
0869 std::cout << " Track " << *myTrack_ << std::endl;
0870 std::cout << " Segments " << segments_.size() << std::endl;
0871 for (unsigned ii = 0; ii < segments_.size(); ++ii) {
0872 std::cout << segments_[ii] << std::endl;
0873 }
0874
0875 return false;
0876 }
0877
0878
0879 if (segiterator->whichDetector() != DetId::Ecal) {
0880 std::cout << " In " << segiterator->whichDetector() << std::endl;
0881
0882 return false;
0883 }
0884
0885
0886
0887
0888 XYZPoint origin;
0889 if (inCm) {
0890 origin = segiterator->positionAtDepthincm(currentdepth_);
0891 } else {
0892 if (EMSHOWER)
0893 origin = segiterator->positionAtDepthinX0(currentdepth_);
0894 if (HADSHOWER)
0895 origin = segiterator->positionAtDepthinL0(currentdepth_);
0896 }
0897
0898 XYZVector newaxis = pivot_.getFirstEdge().Cross(normal_);
0899
0900
0901
0902
0903
0904 plan_ = Plane3D((Vector)normal_, (Point)origin);
0905
0906 unsigned nquads = 0;
0907 double sign = (central_) ? -1. : 1.;
0908 Transform3DR trans((Point)origin,
0909 (Point)(origin + normal_),
0910 (Point)(origin + newaxis),
0911 Point(0, 0, 0),
0912 Point(0., 0., sign),
0913 Point(0., 1., 0.));
0914 for (unsigned ic = 0; ic < ncrystals_; ++ic) {
0915
0916 XYZPoint a, b;
0917
0918
0919
0920
0921
0922 double dummyt;
0923 bool hasbeenpulled = false;
0924 bool behindback = false;
0925 for (unsigned il = 0; il < 4; ++il) {
0926
0927 regionOfInterest_[ic].getLateralEdges(il, a, b);
0928
0929
0930 XYZPoint aprime = a;
0931 if (pulled(origin, normal_, a)) {
0932 b = aprime;
0933 hasbeenpulled = true;
0934 }
0935
0936
0937
0938
0939 XYZPoint xx = (EMSHOWER) ? intersect(plan_, a, b, dummyt, false) : intersect(plan_, a, b, dummyt, true);
0940
0941 if (dummyt > 1)
0942 behindback = true;
0943
0944
0945 if (xx.mag2() != 0) {
0946 corners[il] = xx;
0947 }
0948 }
0949
0950 if (behindback && EMSHOWER)
0951 detailedShowerTail_ = true;
0952
0953 if (corners.size() == 4) {
0954 padsatdepth_[ic] = CrystalPad(ic, corners, trans, bfactor_, !central_);
0955
0956 if (hasbeenpulled)
0957 padsatdepth_[ic].setSurvivalProbability(pulledPadProbability_);
0958 validPads_[ic] = true;
0959 ++nquads;
0960
0961
0962
0963
0964
0965
0966 } else {
0967 padsatdepth_[ic] = CrystalPad();
0968 validPads_[ic] = false;
0969 }
0970 }
0971
0972 if (doreorg_)
0973 reorganizePads();
0974
0975 npadsatdepth_ = nquads;
0976
0977
0978
0979
0980 for (unsigned ic = 0; ic < ncrystals_; ++ic) {
0981 if (!validPads_[ic])
0982 continue;
0983
0984 if (EMSHOWER)
0985 padsatdepth_[ic].resetCorners();
0986
0987 padsatdepth_[ic].extrems(locxmin, locxmax, locymin, locymax);
0988 if (locxmin < xmin_)
0989 xmin_ = locxmin;
0990 if (locymin < ymin_)
0991 ymin_ = locymin;
0992 if (locxmax > xmax_)
0993 xmax_ = locxmax;
0994 if (locymax > ymax_)
0995 ymax_ = locymax;
0996 }
0997
0998 sizex_ = (xmax_ - xmin_) / nx_;
0999 sizey_ = (ymax_ - ymin_) / ny_;
1000
1001
1002 prepareCrystalNumberArray();
1003
1004
1005 ncrackpadsatdepth_ = crackpadsatdepth_.size();
1006
1007 return true;
1008 }
1009
1010 void EcalHitMaker::configureGeometry() {
1011 configuredGeometry_ = true;
1012 for (unsigned ic = 0; ic < ncrystals_; ++ic) {
1013
1014 for (unsigned idir = 0; idir < 8; ++idir) {
1015 unsigned oppdir = CaloDirectionOperations::oppositeDirection(idir);
1016
1017
1018 if (regionOfInterest_[ic].crystalNeighbour(idir).status() >= 0) {
1019
1020 continue;
1021 }
1022
1023 const DetId& oldcell(regionOfInterest_[ic].getDetId());
1024 CaloDirection dir = CaloDirectionOperations::neighbourDirection(idir);
1025 DetId newcell(oldcell);
1026 if (!myCalorimeter->move(newcell, dir)) {
1027
1028 regionOfInterest_[ic].crystalNeighbour(idir).setStatus(-1);
1029 continue;
1030 }
1031
1032
1033 std::map<DetId, unsigned>::const_iterator niter(DetIdMap_.find(newcell));
1034 if (niter == DetIdMap_.end()) {
1035
1036 regionOfInterest_[ic].crystalNeighbour(idir).setStatus(-1);
1037 continue;
1038 }
1039
1040
1041 regionOfInterest_[ic].crystalNeighbour(idir).setNumber(niter->second);
1042
1043
1044 regionOfInterest_[niter->second].crystalNeighbour(oppdir).setNumber(ic);
1045
1046 if (myCalorimeter->borderCrossing(oldcell, newcell)) {
1047 regionOfInterest_[ic].crystalNeighbour(idir).setStatus(1);
1048 regionOfInterest_[niter->second].crystalNeighbour(oppdir).setStatus(1);
1049
1050 } else {
1051 regionOfInterest_[ic].crystalNeighbour(idir).setStatus(0);
1052 regionOfInterest_[niter->second].crystalNeighbour(oppdir).setStatus(0);
1053
1054 }
1055 }
1056 }
1057
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
1067 bool EcalHitMaker::pulled(const XYZPoint& origin, const XYZNormal& normal, XYZPoint& fPoint) const {
1068
1069 double dotproduct = normal.Dot(fPoint - origin);
1070 if (dotproduct <= 0.)
1071 return false;
1072
1073
1074 fPoint -= (1 + dotproduct) * normal;
1075 return true;
1076 }
1077
1078 void EcalHitMaker::prepareCrystalNumberArray() {
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() {
1099 if (hitmaphasbeencalculated_)
1100 return hitMap_;
1101 for (unsigned ic = 0; ic < ncrystals_; ++ic) {
1102
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;
1108
1109 if (onEcal_ == 1) {
1110 CaloHitID current_id(EBDetId(regionOfInterest_[ic].getDetId().rawId()).hashedIndex(), tof, 0);
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);
1114 hitMap_.insert(std::pair<CaloHitID, float>(current_id, hits_[ic]));
1115 }
1116 }
1117 hitmaphasbeencalculated_ = true;
1118 return hitMap_;
1119 }
1120
1121
1122
1123 void EcalHitMaker::reorganizePads() {
1124
1125
1126 crackpadsatdepth_.clear();
1127 crackpadsatdepth_.reserve(etasize_ * phisize_);
1128 ncrackpadsatdepth_ = 0;
1129 std::vector<neighbour> gaps;
1130 std::vector<std::vector<neighbour> > cracks;
1131
1132 cracks.resize(ncrystals_);
1133
1134 for (unsigned iq = 0; iq < ncrystals_; ++iq) {
1135 if (!validPads_[iq])
1136 continue;
1137
1138 gaps.clear();
1139
1140
1141 for (unsigned iside = 0; iside < 4; ++iside) {
1142
1143 CaloDirection thisside = CaloDirectionOperations::Side(iside);
1144 if (regionOfInterest_[iq].crystalNeighbour(iside).toBeGlued()) {
1145
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
1154 if (neighbourstatus == 1) {
1155
1156 cracks[iq].push_back(neighbour(thisside, neighbourNumber));
1157 }
1158 else {
1159 gaps.push_back(neighbour(thisside, neighbourNumber));
1160 }
1161 }
1162 }
1163
1164 gapsLifting(gaps, iq);
1165 }
1166
1167 unsigned ncracks = cracks.size();
1168
1169 for (unsigned icrack = 0; icrack < ncracks; ++icrack) {
1170
1171 cracksPads(cracks[icrack], icrack);
1172 }
1173 }
1174
1175
1176 CLHEP::Hep2Vector& EcalHitMaker::correspondingEdge(neighbour& myneighbour, CaloDirection dir2) {
1177 CaloDirection dir = CaloDirectionOperations::oppositeSide(myneighbour.first);
1178 CaloDirection corner = CaloDirectionOperations::add2d(dir, dir2);
1179
1180 return padsatdepth_[myneighbour.second].edge(corner);
1181 }
1182
1183 bool EcalHitMaker::diagonalEdge(unsigned myPad, CaloDirection dir, CLHEP::Hep2Vector& point) {
1184 unsigned idir = CaloDirectionOperations::neighbourDirection(dir);
1185 if (regionOfInterest_[myPad].crystalNeighbour(idir).status() < 0)
1186 return false;
1187 unsigned nneighbour = regionOfInterest_[myPad].crystalNeighbour(idir).number();
1188 if (!validPads_[nneighbour]) {
1189
1190 return false;
1191 }
1192 point = padsatdepth_[nneighbour].edge(CaloDirectionOperations::oppositeSide(dir));
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;
1204 CaloDirection tmp;
1205 tmp = CaloDirectionOperations::add2d(dirs[0].first, dirs[1].first);
1206 if (tmp == NONE) {
1207 unb = 2;
1208 dir1 = 0;
1209 dir2 = 1;
1210 return true;
1211 }
1212 tmp = CaloDirectionOperations::add2d(dirs[0].first, dirs[2].first);
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
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) {
1236 CaloDirection dir1 = CaloDirectionOperations::add2d(gaps[0].first, EAST);
1237 CaloDirection dir2 = CaloDirectionOperations::add2d(gaps[0].first, WEST);
1238 myPad.edge(dir1) = correspondingEdge(gaps[0], EAST);
1239 myPad.edge(dir2) = correspondingEdge(gaps[0], WEST);
1240 } else {
1241 CaloDirection dir1 = CaloDirectionOperations::add2d(gaps[0].first, NORTH);
1242 CaloDirection dir2 = CaloDirectionOperations::add2d(gaps[0].first, SOUTH);
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 =
1262 CaloDirectionOperations::add2d(CaloDirectionOperations::oppositeSide(gaps[0].first), gaps[1].first);
1263 CaloDirection corner2 =
1264 CaloDirectionOperations::add2d(gaps[0].first, CaloDirectionOperations::oppositeSide(gaps[1].first));
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) {
1270 CaloDirection corner1 = CaloDirectionOperations::add2d(gaps[0].first, NORTH);
1271 CaloDirection corner2 = CaloDirectionOperations::add2d(gaps[0].first, SOUTH);
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 {
1280 CaloDirection corner1 = CaloDirectionOperations::add2d(gaps[0].first, EAST);
1281 CaloDirection corner2 = CaloDirectionOperations::add2d(gaps[0].first, WEST);
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
1297 unsigned iubd, idir1, idir2;
1298 CaloDirection diag;
1299 CLHEP::Hep2Vector point(0., 0.);
1300
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
1306
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;
1313 CaloDirection oppside = CaloDirectionOperations::oppositeSide(ubd);
1314 myPad.edge(CaloDirectionOperations::add2d(oppside, dir1)) = correspondingEdge(gaps[idir1], oppside);
1315 myPad.edge(CaloDirectionOperations::add2d(oppside, dir2)) = correspondingEdge(gaps[idir2], oppside);
1316
1317 }
1318 } else if (ngaps == 4) {
1319
1320
1321
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
1332
1333 }
1334 }
1335
1336 void EcalHitMaker::cracksPads(std::vector<neighbour>& cracks, unsigned iq) {
1337
1338 unsigned ncracks = cracks.size();
1339 CrystalPad& myPad = padsatdepth_[iq];
1340 for (unsigned ic = 0; ic < ncracks; ++ic) {
1341
1342
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
1373 crackpad.setSurvivalProbability(crackPadProbability_);
1374 crackpadsatdepth_.push_back(crackpad);
1375 }
1376
1377 }
1378
1379 bool EcalHitMaker::inside3D(const std::vector<XYZPoint>& corners, const XYZPoint& p) const {
1380
1381
1382
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 }