00001 #include "DataFormats/DetId/interface/DetId.h"
00002 #include "DataFormats/EcalDetId/interface/EcalSubdetector.h"
00003 #include "DataFormats/EcalDetId/interface/EBDetId.h"
00004 #include "DataFormats/EcalDetId/interface/EEDetId.h"
00005
00006
00007
00008
00009
00010 #include "Geometry/CaloGeometry/interface/CaloSubdetectorGeometry.h"
00011 #include "FastSimulation/CaloHitMakers/interface/EcalHitMaker.h"
00012 #include "FastSimulation/CaloGeometryTools/interface/CaloGeometryHelper.h"
00013 #include "FastSimulation/CaloGeometryTools/interface/CrystalWindowMap.h"
00014 #include "FastSimulation/CaloGeometryTools/interface/CaloDirectionOperations.h"
00015 #include "FastSimulation/Event/interface/FSimVertex.h"
00016 #include "FastSimulation/Event/interface/FSimTrack.h"
00017 #include "FastSimulation/CalorimeterProperties/interface/PreshowerLayer1Properties.h"
00018 #include "FastSimulation/CalorimeterProperties/interface/PreshowerLayer2Properties.h"
00019 #include "FastSimulation/CalorimeterProperties/interface/HCALProperties.h"
00020 #include "FastSimulation/Utilities/interface/RandomEngine.h"
00021
00022
00023
00024 #include "FastSimulation/CaloGeometryTools/interface/Transform3DPJ.h"
00025
00026 #include <algorithm>
00027 #include <cmath>
00028
00029 typedef ROOT::Math::Plane3D::Vector Vector;
00030 typedef ROOT::Math::Plane3D::Point Point;
00031 typedef ROOT::Math::Transform3DPJ Transform3DR;
00032
00033 EcalHitMaker::EcalHitMaker(CaloGeometryHelper * theCalo,
00034 const XYZPoint& ecalentrance,
00035 const DetId& cell, int onEcal,
00036 unsigned size, unsigned showertype,
00037 const RandomEngine* engine):
00038 CaloHitMaker(theCalo,DetId::Ecal,((onEcal==1)?EcalBarrel:EcalEndcap),onEcal,showertype),
00039 EcalEntrance_(ecalentrance),
00040 onEcal_(onEcal),
00041 myTrack_(NULL),
00042 random(engine)
00043 {
00044 #ifdef FAMOSDEBUG
00045 myHistos = Histos::instance();
00046 #endif
00047
00048 simulatePreshower_ = true;
00049 X0depthoffset_ = 0. ;
00050 X0PS1_ = 0.;
00051 X0PS2_ = 0.;
00052 X0PS2EE_ = 0.;
00053 X0ECAL_ = 0.;
00054 X0EHGAP_ = 0.;
00055 X0HCAL_ = 0.;
00056 L0PS1_ = 0.;
00057 L0PS2_ = 0.;
00058 L0PS2EE_ = 0.;
00059 L0ECAL_ = 0.;
00060 L0EHGAP_ = 0.;
00061 L0HCAL_ = 0.;
00062 maxX0_ = 0.;
00063 totalX0_ = 0;
00064 totalL0_ = 0.;
00065 pulledPadProbability_ = 1.;
00066 outsideWindowEnergy_ = 0.;
00067 rearleakage_ = 0.;
00068 bfactor_ = 1.;
00069 ncrystals_ = 0;
00070
00071 doreorg_ = !showertype;
00072
00073 hitmaphasbeencalculated_ = false;
00074
00075 if(onEcal)
00076 myCalorimeter->buildCrystal(cell,pivot_);
00077 else
00078 pivot_=Crystal();
00079 central_=onEcal==1;
00080 ecalFirstSegment_=-1;
00081
00082 myCrystalWindowMap_ = 0;
00083
00084
00085 if(!onEcal) return;
00086
00087
00088 etasize_ = size;
00089 phisize_ = size;
00090
00091
00092
00093 myCalorimeter->getWindow(pivot_.getDetId(),size,size,CellsWindow_);
00094
00095 buildGeometry();
00096
00097
00098 truncatedGrid_ = CellsWindow_.size()!=(etasize_*phisize_);
00099
00100
00101 mycorners.resize(4);
00102 corners.resize(4);
00103
00104 #ifdef DEBUGGW
00105 myHistos->fill("h10",EcalEntrance_.eta(),CellsWindow_.size());
00106 if(onEcal==2)
00107 {
00108 myHistos->fill("h20",EcalEntrance_.perp(),CellsWindow_.size());
00109 if(EcalEntrance_.perp()>70&&EcalEntrance_.perp()<80&&CellsWindow_.size()<35)
00110 {
00111 std::cout << " Truncated grid " << CellsWindow_.size() << " " << EcalEntrance_.perp() << std::endl;
00112 std::cout << " Pivot " << myCalorimeter->getEcalEndcapGeometry()->getGeometry(pivot_.getDetId())->getPosition().perp();
00113 std::cout << EEDetId(pivot_.getDetId()) << std::endl;
00114
00115 std::cout << " Test getClosestCell " << EcalEntrance_ << std::endl;
00116 DetId testcell = myCalorimeter->getClosestCell(EcalEntrance_, true, false);
00117 std::cout << " Result "<< EEDetId(testcell) << std::endl;
00118 std::cout << " Position " << myCalorimeter->getEcalEndcapGeometry()->getGeometry(testcell)->getPosition() << std::endl;
00119 }
00120 }
00121
00122 #endif
00123
00124 }
00125
00126 EcalHitMaker::~EcalHitMaker()
00127 {
00128 if (myCrystalWindowMap_ != 0)
00129 {
00130 delete myCrystalWindowMap_;
00131 }
00132 }
00133
00134 bool
00135 EcalHitMaker::addHitDepth(double r,double phi,double depth)
00136 {
00137
00138
00139 depth+=X0depthoffset_;
00140 double sp(1.);
00141 r*=radiusFactor_;
00142 CLHEP::Hep2Vector point(r*std::cos(phi),r*std::sin(phi));
00143
00144 unsigned xtal=fastInsideCell(point,sp);
00145
00146
00147
00148
00149
00150
00151
00152 if(xtal<1000)
00153 {
00154
00155
00156 if(regionOfInterest_[xtal].getX0Back()>depth)
00157 {
00158 hits_[xtal]+=spotEnergy;
00159
00160 return true;
00161 }
00162 else
00163 {
00164 rearleakage_+=spotEnergy;
00165 }
00166 }
00167 else
00168 {
00169
00170
00171
00172
00173 }
00174
00175 outsideWindowEnergy_+=spotEnergy;
00176 return false;
00177 }
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194 bool
00195 EcalHitMaker::addHit(double r,double phi,unsigned layer)
00196 {
00197
00198
00199 double sp(1.);
00200
00201 r*=radiusFactor_;
00202 CLHEP::Hep2Vector point(r*std::cos(phi),r*std::sin(phi));
00203
00204
00205 unsigned xtal=fastInsideCell(point,sp);
00206
00207 if(xtal<1000)
00208 {
00209 if(sp==1.)
00210 hits_[xtal]+=spotEnergy;
00211 else
00212 hits_[xtal]+=(random->flatShoot()<sp)*spotEnergy;
00213 return true;
00214 }
00215
00216 outsideWindowEnergy_+=spotEnergy;
00217
00218
00219
00220
00221
00222
00223
00224 return false;
00225 }
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243 unsigned
00244 EcalHitMaker::fastInsideCell(const CLHEP::Hep2Vector & point,double & sp,bool debug)
00245 {
00246
00247
00248 bool found=false;
00249 unsigned niter=0;
00250
00251 unsigned d1,d2;
00252 convertIntegerCoordinates(point.x(),point.y(),d1,d2);
00253
00254 if(d1>=nx_||d2>=ny_)
00255 {
00256
00257 return 9999;
00258 }
00259 unsigned cell=myCrystalNumberArray_[d1][d2];
00260
00261
00262 if (validPads_[cell]&&padsatdepth_[cell].inside(point))
00263 {
00264
00265 sp = padsatdepth_[cell].survivalProbability();
00266 return cell;
00267 }
00268
00269
00270 bool status(true);
00271 const std::vector<unsigned>& localCellVector(myCrystalWindowMap_->getCrystalWindow(cell,status));
00272 if(status)
00273 {
00274 unsigned size=localCellVector.size();
00275
00276
00277
00278
00279
00280
00281
00282
00283 for(unsigned ic=0;ic<8&&ic<size;++ic)
00284 {
00285 unsigned iq=localCellVector[ic];
00286
00287
00288
00289 if(validPads_[iq]&&padsatdepth_[iq].inside(point))
00290 {
00291
00292
00293 sp = padsatdepth_[iq].survivalProbability();
00294
00295
00296 return iq;
00297 }
00298
00299
00300 ++niter;
00301 }
00302 }
00303 if(debug) std::cout << " not found in a quad, let's check the " << ncrackpadsatdepth_ << " cracks " << std::endl;
00304
00305
00306
00307 unsigned iquad=0;
00308 unsigned iquadinside=999;
00309 while(iquad<ncrackpadsatdepth_&&!found)
00310 {
00311
00312 if(crackpadsatdepth_[iquad].inside(point))
00313 {
00314 iquadinside=iquad;
00315 found=true;
00316 sp = crackpadsatdepth_[iquad].survivalProbability();
00317 }
00318 ++iquad;
00319 ++niter;
00320 }
00321
00322 if(!found&&debug) std::cout << " Not found in the cracks " << std::endl;
00323 return (found) ? crackpadsatdepth_[iquadinside].getNumber(): 9999;
00324 }
00325
00326
00327 void
00328 EcalHitMaker::setTrackParameters(const XYZNormal& normal,
00329 double X0depthoffset,
00330 const FSimTrack& theTrack)
00331 {
00332
00333
00334 intersections_.clear();
00335
00336 intersections_.reserve(50);
00337 myTrack_=&theTrack;
00338 normal_=normal.Unit();
00339 X0depthoffset_=X0depthoffset;
00340 cellLine(intersections_);
00341 buildSegments(intersections_);
00342
00343
00344
00345
00346
00347
00348
00349
00350 if(EMSHOWER&&onEcal_&&ecalTotalX0()>0.)
00351 {
00352
00353 for(unsigned ic=0;ic<ncrystals_;++ic)
00354 {
00355 for(unsigned idir=0;idir<4;++idir)
00356 {
00357 XYZVector norm=regionOfInterest_[ic].exitingNormal(CaloDirectionOperations::Side(idir));
00358 regionOfInterest_[ic].crystalNeighbour(idir).setToBeGlued((norm.Dot(normal_)<0.));
00359 }
00360
00361
00362 if(EMSHOWER)
00363 {
00364 XYZVector dir=regionOfInterest_[ic].getBackCenter()-segments_[ecalFirstSegment_].entrance();
00365 double dist=dir.Dot(normal_);
00366 double absciss= dist+segments_[ecalFirstSegment_].sEntrance();
00367 std::vector<CaloSegment>::const_iterator segiterator;
00368
00369
00370
00371
00372 segiterator = find_if(segments_.begin(),segments_.end(),CaloSegment::inSegment(absciss));
00373
00374 if(segiterator==segments_.end() )
00375 {
00376
00377
00378 regionOfInterest_[ic].setX0Back(9999);
00379 }
00380 else
00381 {
00382 DetId::Detector det(segiterator->whichDetector());
00383 if(det!=DetId::Ecal)
00384 {
00385 regionOfInterest_[ic].setX0Back(9999);
00386 }
00387 else
00388 {
00389 double x0=segiterator->x0FromCm(dist);
00390 if(x0<maxX0_) maxX0_=x0;
00391 regionOfInterest_[ic].setX0Back(x0);
00392 }
00393 }
00394
00395
00396
00397
00398
00399
00400
00401
00402 }
00403 }
00404
00405 }
00406
00407 }
00408
00409
00410 void
00411 EcalHitMaker::cellLine(std::vector<CaloPoint>& cp)
00412 {
00413 cp.clear();
00414
00415
00416 if(!central_&&onEcal_&&simulatePreshower_) preshowerCellLine(cp);
00417 if(onEcal_)ecalCellLine(EcalEntrance_,EcalEntrance_+normal_,cp);
00418
00419
00420 XYZPoint vertex(myTrack_->vertex().position().Vect());
00421
00422
00423 XYZVector dir(0.,0.,0.);
00424 if(myTrack_->onLayer1())
00425 {
00426 vertex=(myTrack_->layer1Entrance().vertex()).Vect();
00427 dir=myTrack_->layer1Entrance().Vect().Unit();
00428 }
00429 else if(myTrack_->onLayer2())
00430 {
00431 vertex=(myTrack_->layer2Entrance().vertex()).Vect();
00432 dir=myTrack_->layer2Entrance().Vect().Unit();
00433 }
00434 else if(myTrack_->onEcal())
00435 {
00436 vertex=(myTrack_->ecalEntrance().vertex()).Vect();
00437 dir=myTrack_->ecalEntrance().Vect().Unit();
00438 }
00439 else if(myTrack_->onHcal())
00440 {
00441 vertex=(myTrack_->hcalEntrance().vertex()).Vect();
00442 dir=myTrack_->hcalEntrance().Vect().Unit();
00443 }
00444 else if(myTrack_->onVFcal()==2)
00445 {
00446 vertex=(myTrack_->vfcalEntrance().vertex()).Vect();
00447 dir=myTrack_->vfcalEntrance().Vect().Unit();
00448 }
00449 else
00450 {
00451 std::cout << " Problem with the grid " << std::endl;
00452 }
00453
00454
00455 vertex -= 5.*dir;
00456 CaloPoint::DistanceToVertex myDistance(vertex);
00457 sort(cp.begin(),cp.end(),myDistance);
00458
00459
00460
00461 hcalCellLine(cp);
00462
00463
00464
00465
00466
00467
00468
00469
00470 }
00471
00472
00473 void
00474 EcalHitMaker::preshowerCellLine(std::vector<CaloPoint>& cp) const
00475 {
00476
00477
00478
00479
00480
00481 if(myTrack_->onLayer1())
00482 {
00483 XYZPoint point1=(myTrack_->layer1Entrance().vertex()).Vect();
00484 double phys_eta=myTrack_->layer1Entrance().eta();
00485 double cmthickness =
00486 myCalorimeter->layer1Properties(1)->thickness(phys_eta);
00487
00488 if(cmthickness>0)
00489 {
00490 XYZVector dir=myTrack_->layer1Entrance().Vect().Unit();
00491 XYZPoint point2=point1+dir*cmthickness;
00492
00493 CaloPoint cp1(DetId::Ecal,EcalPreshower,1,point1);
00494 CaloPoint cp2(DetId::Ecal,EcalPreshower,1,point2);
00495 cp.push_back(cp1);
00496 cp.push_back(cp2);
00497 }
00498 else
00499 {
00500
00501 }
00502 }
00503
00504
00505 if(myTrack_->onLayer2())
00506 {
00507 XYZPoint point1=(myTrack_->layer2Entrance().vertex()).Vect();
00508 double phys_eta=myTrack_->layer2Entrance().eta();
00509 double cmthickness =
00510 myCalorimeter->layer2Properties(1)->thickness(phys_eta);
00511 if(cmthickness>0)
00512 {
00513 XYZVector dir=myTrack_->layer2Entrance().Vect().Unit();
00514 XYZPoint point2=point1+dir*cmthickness;
00515
00516
00517 CaloPoint cp1(DetId::Ecal,EcalPreshower,2,point1);
00518 CaloPoint cp2(DetId::Ecal,EcalPreshower,2,point2);
00519
00520 cp.push_back(cp1);
00521 cp.push_back(cp2);
00522 }
00523 else
00524 {
00525
00526 }
00527 }
00528
00529 }
00530
00531 void
00532 EcalHitMaker::hcalCellLine(std::vector<CaloPoint>& cp) const
00533 {
00534
00535
00536 int onHcal=myTrack_->onHcal();
00537
00538 if(onHcal<=2&&onHcal>0)
00539 {
00540 XYZPoint point1=(myTrack_->hcalEntrance().vertex()).Vect();
00541
00542 double eta=point1.eta();
00543
00544 double thickness= myCalorimeter->hcalProperties(onHcal)->thickness(eta);
00545 cp.push_back(CaloPoint(DetId::Hcal,point1));
00546 XYZVector dir=myTrack_->hcalEntrance().Vect().Unit();
00547 XYZPoint point2=point1+dir*thickness;
00548
00549 cp.push_back(CaloPoint(DetId::Hcal,point2));
00550
00551 }
00552 int onVFcal=myTrack_->onVFcal();
00553 if(onVFcal==2)
00554 {
00555 XYZPoint point1=(myTrack_->vfcalEntrance().vertex()).Vect();
00556 double eta=point1.eta();
00557
00558 double thickness= myCalorimeter->hcalProperties(3)->thickness(eta);
00559 cp.push_back(CaloPoint(DetId::Hcal,point1));
00560 XYZVector dir=myTrack_->vfcalEntrance().Vect().Unit();
00561 if(thickness>0)
00562 {
00563 XYZPoint point2=point1+dir*thickness;
00564 cp.push_back(CaloPoint(DetId::Hcal,point2));
00565 }
00566
00567 }
00568 }
00569
00570 void
00571 EcalHitMaker::ecalCellLine(const XYZPoint& a,const XYZPoint& b,std::vector<CaloPoint>& cp)
00572 {
00573
00574
00575 unsigned ic=0;
00576 double t;
00577 XYZPoint xp;
00578 DetId c_entrance,c_exit;
00579 bool entrancefound(false),exitfound(false);
00580
00581
00582
00583
00584 double angle=std::acos(normal_.Dot(regionOfInterest_[0].getAxis().Unit()));
00585
00586
00587 double backdistance=std::sqrt(regionOfInterest_[0].getAxis().mag2())*std::tan(angle);
00588
00589
00590
00591 unsigned ncrystals=(unsigned)(backdistance*0.45);
00592 unsigned highlim=(ncrystals+4);
00593 highlim*=highlim;
00594 if(highlim>ncrystals_) highlim=ncrystals_;
00595
00596
00597
00598
00599 while(ic<ncrystals_&&(ic<highlim||!exitfound))
00600 {
00601
00602
00603 {
00604 const Plane3D& plan=regionOfInterest_[ic].getFrontPlane();
00605
00606
00607 xp=intersect(plan,a,b,t,false);
00608 regionOfInterest_[ic].getFrontSide(corners);
00609
00610
00611 if(inside3D(corners,xp))
00612 {
00613 cp.push_back(CaloPoint(regionOfInterest_[ic].getDetId(),UP,xp));
00614 entrancefound=true;
00615 c_entrance=regionOfInterest_[ic].getDetId();
00616
00617 }
00618 }
00619
00620
00621
00622 {
00623 const Plane3D& plan=regionOfInterest_[ic].getBackPlane();
00624
00625
00626 xp=intersect(plan,a,b,t,false);
00627 regionOfInterest_[ic].getBackSide(corners);
00628
00629
00630 if(inside3D(corners,xp))
00631 {
00632 cp.push_back(CaloPoint(regionOfInterest_[ic].getDetId(),DOWN,xp));
00633 exitfound=true;
00634 c_exit=regionOfInterest_[ic].getDetId();
00635
00636
00637 }
00638 }
00639
00640 if(entrancefound&&exitfound&&c_entrance==c_exit) return;
00641
00642 for(unsigned iside=0;iside<4;++iside)
00643 {
00644 const Plane3D& plan=regionOfInterest_[ic].getLateralPlane(iside);
00645 xp=intersect(plan,a,b,t,false);
00646
00647
00648 regionOfInterest_[ic].getLateralSide(iside,corners);
00649
00650
00651 if(inside3D(corners,xp))
00652 {
00653 cp.push_back(CaloPoint(regionOfInterest_[ic].getDetId(),CaloDirectionOperations::Side(iside),xp));
00654
00655 }
00656 }
00657
00658 ++ic;
00659 }
00660 }
00661
00662
00663 void
00664 EcalHitMaker::buildSegments(const std::vector<CaloPoint>& cp)
00665 {
00666
00667
00668 unsigned size=cp.size();
00669 if(size%2!=0)
00670 {
00671
00672 return;
00673 }
00674
00675 unsigned nsegments=size/2;
00676 segments_.reserve(nsegments);
00677 if (size==0) return;
00678
00679 double s=0.;
00680 double sX0=0.;
00681 double sL0=0.;
00682
00683 unsigned ncrossedxtals = 0;
00684 unsigned is=0;
00685 while(is<nsegments)
00686 {
00687
00688 if(cp[2*is].getDetId()!=cp[2*is+1].getDetId()&&
00689 cp[2*is].whichDetector()!=DetId::Hcal&&
00690 cp[2*is+1].whichDetector()!=DetId::Hcal)
00691 {
00692
00693
00694
00695
00696 ++is;
00697 continue;
00698 }
00699
00700
00701
00702
00703 if(cp[2*is].whichDetector()==DetId::Ecal && cp[2*is].whichSubDetector()==EcalPreshower && cp[2*is].whichLayer()==1)
00704 {
00705 if(cp[2*is+1].whichDetector()==DetId::Ecal && cp[2*is+1].whichSubDetector()==EcalPreshower && cp[2*is+1].whichLayer()==1)
00706 {
00707 CaloSegment preshsegment(cp[2*is],cp[2*is+1],s,sX0,sL0,CaloSegment::PS,myCalorimeter);
00708 segments_.push_back(preshsegment);
00709
00710 s+=preshsegment.length();
00711 sX0+=preshsegment.X0length();
00712 sL0+=preshsegment.L0length();
00713 X0PS1_+=preshsegment.X0length();
00714 L0PS1_+=preshsegment.L0length();
00715 }
00716 else
00717 {
00718 std::cout << " Strange segment between Preshower1 and " << cp[2*is+1].whichDetector();
00719 std::cout << std::endl;
00720 }
00721 ++is;
00722 continue;
00723 }
00724
00725
00726
00727 if(cp[2*is].whichDetector()==DetId::Ecal && cp[2*is].whichSubDetector()==EcalPreshower && cp[2*is].whichLayer()==2)
00728 {
00729 if(cp[2*is+1].whichDetector()==DetId::Ecal && cp[2*is+1].whichSubDetector()==EcalPreshower && cp[2*is+1].whichLayer()==2)
00730 {
00731 CaloSegment preshsegment(cp[2*is],cp[2*is+1],s,sX0,sL0,CaloSegment::PS,myCalorimeter);
00732 segments_.push_back(preshsegment);
00733
00734 s+=preshsegment.length();
00735 sX0+=preshsegment.X0length();
00736 sL0+=preshsegment.L0length();
00737 X0PS2_+=preshsegment.X0length();
00738 L0PS2_+=preshsegment.L0length();
00739
00740
00741 if(is<(nsegments-1) && cp[2*is+2].whichDetector()==DetId::Ecal && cp[2*is+2].whichSubDetector()==EcalEndcap)
00742 {
00743 CaloSegment gapsef(cp[2*is+1],cp[2*is+2],s,sX0,sL0,CaloSegment::PSEEGAP,myCalorimeter);
00744 segments_.push_back(gapsef);
00745 s+=gapsef.length();
00746 sX0+=gapsef.X0length();
00747 sL0+=gapsef.L0length();
00748 X0PS2EE_+=gapsef.X0length();
00749 L0PS2EE_+=gapsef.L0length();
00750
00751 }
00752 }
00753 else
00754 {
00755 std::cout << " Strange segment between Preshower2 and " << cp[2*is+1].whichDetector();
00756 std::cout << std::endl;
00757 }
00758 ++is;
00759 continue;
00760 }
00761
00762
00763
00764 if(cp[2*is].whichDetector()==DetId::Ecal && (cp[2*is].whichSubDetector()==EcalBarrel || cp[2*is].whichSubDetector()==EcalEndcap))
00765 {
00766 if(cp[2*is+1].whichDetector()==DetId::Ecal && (cp[2*is+1].whichSubDetector()==EcalBarrel || cp[2*is+1].whichSubDetector()==EcalEndcap) )
00767 {
00768 DetId cell2=cp[2*is+1].getDetId();
00769
00770 if (ecalFirstSegment_<0) ecalFirstSegment_=segments_.size();
00771
00772
00773 if(cp[2*is].getDetId()==cell2)
00774 {
00775 CaloSegment segment(cp[2*is],cp[2*is+1],s,sX0,sL0,CaloSegment::PbWO4,myCalorimeter);
00776 segments_.push_back(segment);
00777
00778 s+=segment.length();
00779 sX0+=segment.X0length();
00780 sL0+=segment.L0length();
00781 X0ECAL_+=segment.X0length();
00782 L0ECAL_+=segment.L0length();
00783 ++ncrossedxtals;
00784 ++is;
00785 }
00786 else
00787 {
00788 std::cout << " One more bug in the segment " <<std::endl;
00789 ++is;
00790 }
00791
00792 if(is>0 && is<nsegments)
00793 {
00794 DetId cell3=cp[2*is].getDetId();
00795 if(cp[2*is].whichDetector()!=DetId::Hcal)
00796 {
00797
00798 bool bordercrossing=myCalorimeter->borderCrossing(cell2,cell3);
00799 CaloSegment cracksegment(cp[2*is-1],cp[2*is],s,sX0,sL0,(bordercrossing)?CaloSegment::CRACK:CaloSegment::GAP,myCalorimeter);
00800 segments_.push_back(cracksegment);
00801 s+=cracksegment.length();
00802 sX0+=cracksegment.X0length();
00803 sL0+=cracksegment.L0length();
00804 X0ECAL_+=cracksegment.X0length();
00805 L0ECAL_+=cracksegment.L0length();
00806
00807 }
00808 else
00809 {
00810
00811
00812 CaloSegment cracksegment(cp[2*is-1],cp[2*is],s,sX0,sL0,CaloSegment::ECALHCALGAP,myCalorimeter);
00813 segments_.push_back(cracksegment);
00814 s+=cracksegment.length();
00815 sX0+=cracksegment.X0length();
00816 sL0+=cracksegment.L0length();
00817 X0EHGAP_+=cracksegment.X0length();
00818 L0EHGAP_+=cracksegment.L0length();
00819 }
00820 }
00821 continue;
00822 }
00823 else
00824 {
00825 std::cout << " Strange segment between " << cp[2*is].whichDetector();
00826 std::cout << " and " << cp[2*is+1].whichDetector() << std::endl;
00827 ++is;
00828 continue;
00829 }
00830 }
00831
00832
00833 if(cp[2*is].whichDetector()==DetId::Hcal&&cp[2*is+1].whichDetector()==DetId::Hcal)
00834 {
00835 CaloSegment segment(cp[2*is],cp[2*is+1],s,sX0,sL0,CaloSegment::HCAL,myCalorimeter);
00836 segments_.push_back(segment);
00837 s+=segment.length();
00838 sX0+=segment.X0length();
00839 sL0+=segment.L0length();
00840 X0HCAL_+=segment.X0length();
00841 L0HCAL_+=segment.L0length();
00842
00843 ++is;
00844 }
00845 }
00846
00847
00848
00849
00850
00851 totalX0_ = X0PS1_+X0PS2_+X0PS2EE_+X0ECAL_+X0EHGAP_+X0HCAL_;
00852 totalL0_ = L0PS1_+L0PS2_+L0PS2EE_+L0ECAL_+L0EHGAP_+L0HCAL_;
00853
00854
00855 #ifdef DEBUGCELLLINE
00856 myHistos->fill("h200",fabs(EcalEntrance_.eta()),X0ECAL_);
00857 myHistos->fill("h210",EcalEntrance_.phi(),X0ECAL_);
00858 if(X0ECAL_<20)
00859 myHistos->fill("h212",EcalEntrance_.phi(),X0ECAL_);
00860
00861
00862
00863
00864
00865
00866
00867 myHistos->fillByNumber("h30",ncrossedxtals,EcalEntrance_.eta(),X0ECAL_);
00868
00869 double zvertex = myTrack_->vertex().position().z();
00870
00871 myHistos->fill("h310",EcalEntrance_.eta(),X0ECAL_);
00872 if(X0ECAL_<22) myHistos->fill("h410",EcalEntrance_.phi());
00873 myHistos->fill("h400",zvertex,X0ECAL_);
00874 #endif
00875
00876
00877 }
00878
00879 void
00880 EcalHitMaker::buildGeometry()
00881 {
00882 configuredGeometry_ = false;
00883 ncrystals_ = CellsWindow_.size();
00884
00885 padsatdepth_.resize(ncrystals_);
00886
00887
00888 ny_= phisize_;
00889 nx_=ncrystals_/ny_;
00890 std::vector<unsigned> empty;
00891 empty.resize(ny_,0);
00892 myCrystalNumberArray_.reserve((unsigned)nx_);
00893 for(unsigned inx=0;inx<(unsigned)nx_;++inx)
00894 {
00895 myCrystalNumberArray_.push_back(empty);
00896 }
00897
00898 hits_.resize(ncrystals_,0.);
00899 regionOfInterest_.clear();
00900 regionOfInterest_.resize(ncrystals_);
00901 validPads_.resize(ncrystals_);
00902 for(unsigned ic=0;ic<ncrystals_;++ic)
00903 {
00904 myCalorimeter->buildCrystal(CellsWindow_[ic],regionOfInterest_[ic]);
00905 regionOfInterest_[ic].setNumber(ic);
00906 DetIdMap_.insert(std::pair<DetId,unsigned>(CellsWindow_[ic],ic));
00907 }
00908
00909
00910 myCrystalWindowMap_ = new CrystalWindowMap(myCalorimeter,regionOfInterest_);
00911 }
00912
00913
00914
00915
00916 bool
00917 EcalHitMaker::getPads(double depth,bool inCm)
00918 {
00919
00920
00921
00922
00923 if(EMSHOWER && !configuredGeometry_) configureGeometry();
00924
00925
00926 radiusFactor_ = (EMSHOWER) ? moliereRadius*radiusCorrectionFactor_:interactionLength;
00927 detailedShowerTail_ = false;
00928 if(EMSHOWER)
00929 currentdepth_ = depth+X0depthoffset_;
00930 else
00931 currentdepth_ = depth;
00932
00933
00934
00935
00936
00937
00938
00939
00940
00941 ncrackpadsatdepth_=0;
00942
00943 xmin_=ymin_=999;
00944 xmax_=ymax_=-999;
00945 double locxmin,locxmax,locymin,locymax;
00946
00947
00948 std::vector<CaloSegment>::const_iterator segiterator;
00949
00950
00951 if(inCm)
00952 {
00953 segiterator = find_if(segments_.begin(),segments_.end(),CaloSegment::inSegment(currentdepth_));
00954 }
00955 else
00956 {
00957
00958 if(EMSHOWER)
00959 segiterator = find_if(segments_.begin(),segments_.end(),CaloSegment::inX0Segment(currentdepth_));
00960
00961
00962 if(HADSHOWER)
00963 segiterator = find_if(segments_.begin(),segments_.end(),CaloSegment::inL0Segment(currentdepth_));
00964 }
00965 if(segiterator==segments_.end())
00966 {
00967 std::cout << " FamosGrid: Could not go at such depth " << depth << std::endl;
00968 std::cout << " EMSHOWER " << EMSHOWER << std::endl;
00969 std::cout << " Track " << *myTrack_ << std::endl;
00970 std::cout << " Segments " << segments_.size() << std::endl;
00971 for(unsigned ii=0; ii<segments_.size() ; ++ii)
00972 {
00973 std::cout << segments_[ii] << std::endl;
00974 }
00975
00976 return false;
00977 }
00978
00979
00980 if(segiterator->whichDetector()!=DetId::Ecal)
00981 {
00982 std::cout << " In " << segiterator->whichDetector() << std::endl;
00983
00984 return false;
00985 }
00986
00987
00988
00989
00990 XYZPoint origin;
00991 if(inCm)
00992 {
00993 origin=segiterator->positionAtDepthincm(currentdepth_);
00994 }
00995 else
00996 {
00997 if(EMSHOWER)
00998 origin=segiterator->positionAtDepthinX0(currentdepth_);
00999 if(HADSHOWER)
01000 origin=segiterator->positionAtDepthinL0(currentdepth_);
01001 }
01002
01003 XYZVector newaxis=pivot_.getFirstEdge().Cross(normal_);
01004
01005
01006
01007
01008
01009 plan_ = Plane3D((Vector)normal_,(Point)origin);
01010
01011 unsigned nquads=0;
01012 double sign=(central_) ? -1.: 1.;
01013 Transform3DR trans((Point)origin,(Point)(origin+normal_),(Point)(origin+newaxis),
01014 Point(0,0,0), Point(0.,0.,sign), Point(0.,1.,0.));
01015 for(unsigned ic=0;ic<ncrystals_;++ic)
01016 {
01017
01018 XYZPoint a,b;
01019
01020
01021
01022
01023
01024 double dummyt;
01025 bool hasbeenpulled=false;
01026 bool behindback=false;
01027 for(unsigned il=0;il<4;++il)
01028 {
01029
01030 regionOfInterest_[ic].getLateralEdges(il,a,b);
01031
01032
01033 XYZPoint aprime=a;
01034 if(pulled(origin,normal_,a))
01035 {
01036 b=aprime;
01037 hasbeenpulled=true;
01038 }
01039
01040
01041
01042
01043 XYZPoint xx=(EMSHOWER)?intersect(plan_,a,b,dummyt,false):intersect(plan_,a,b,dummyt,true);
01044
01045 if(dummyt>1) behindback=true;
01046
01047
01048 if(xx.mag2()!=0)
01049 {
01050 corners[il] = xx;
01051 }
01052 }
01053
01054 if(behindback&&EMSHOWER) detailedShowerTail_=true;
01055
01056 if(corners.size()==4)
01057 {
01058 padsatdepth_[ic]=CrystalPad(ic,corners,trans,bfactor_,!central_);
01059
01060 if(hasbeenpulled) padsatdepth_[ic].setSurvivalProbability(pulledPadProbability_);
01061 validPads_[ic]=true;
01062 ++nquads;
01063
01064
01065
01066
01067
01068
01069 }
01070 else
01071 {
01072 padsatdepth_[ic]=CrystalPad();
01073 validPads_[ic]=false;
01074 }
01075 }
01076
01077 if(doreorg_)reorganizePads();
01078
01079 npadsatdepth_=nquads;
01080
01081
01082
01083
01084
01085 for(unsigned ic=0;ic<ncrystals_;++ic)
01086 {
01087
01088 if (!validPads_[ic]) continue;
01089
01090 if(EMSHOWER) padsatdepth_[ic].resetCorners();
01091
01092 padsatdepth_[ic].extrems(locxmin,locxmax,locymin,locymax);
01093 if(locxmin<xmin_) xmin_=locxmin;
01094 if(locymin<ymin_) ymin_=locymin;
01095 if(locxmax>xmax_) xmax_=locxmax;
01096 if(locymax>ymax_) ymax_=locymax;
01097 }
01098
01099 sizex_=(xmax_-xmin_)/nx_;
01100 sizey_=(ymax_-ymin_)/ny_;
01101
01102
01103
01104 prepareCrystalNumberArray();
01105
01106
01107 ncrackpadsatdepth_=crackpadsatdepth_.size();
01108
01109 return true;
01110 }
01111
01112
01113
01114
01115 void
01116 EcalHitMaker::configureGeometry()
01117 {
01118 configuredGeometry_=true;
01119 for(unsigned ic=0;ic<ncrystals_;++ic)
01120 {
01121
01122 for(unsigned idir=0;idir<8;++idir)
01123 {
01124
01125 unsigned oppdir=CaloDirectionOperations::oppositeDirection(idir);
01126
01127
01128 if(regionOfInterest_[ic].crystalNeighbour(idir).status()>=0)
01129 {
01130
01131 continue ;
01132 }
01133
01134 const DetId & oldcell(regionOfInterest_[ic].getDetId());
01135 CaloDirection dir=CaloDirectionOperations::neighbourDirection(idir);
01136 DetId newcell(oldcell);
01137 if(!myCalorimeter->move(newcell,dir))
01138 {
01139
01140 regionOfInterest_[ic].crystalNeighbour(idir).setStatus(-1);
01141 continue;
01142 }
01143
01144
01145 std::map<DetId,unsigned>::const_iterator niter(DetIdMap_.find(newcell));
01146 if(niter==DetIdMap_.end())
01147 {
01148
01149 regionOfInterest_[ic].crystalNeighbour(idir).setStatus(-1);
01150 continue;
01151 }
01152
01153
01154 regionOfInterest_[ic].crystalNeighbour(idir).setNumber(niter->second);
01155
01156
01157 regionOfInterest_[niter->second].crystalNeighbour(oppdir).setNumber(ic);
01158
01159 if(myCalorimeter->borderCrossing(oldcell,newcell))
01160 {
01161 regionOfInterest_[ic].crystalNeighbour(idir).setStatus(1);
01162 regionOfInterest_[niter->second].crystalNeighbour(oppdir).setStatus(1);
01163
01164 }
01165 else
01166 {
01167 regionOfInterest_[ic].crystalNeighbour(idir).setStatus(0);
01168 regionOfInterest_[niter->second].crystalNeighbour(oppdir).setStatus(0);
01169
01170 }
01171 }
01172 }
01173
01174 double theta=EcalEntrance_.theta();
01175 if(theta>M_PI_2) theta=M_PI-theta;
01176 bfactor_=1./(1.+0.133*theta);
01177 if(myCalorimeter->magneticField()==0. ) bfactor_=1.;
01178 }
01179
01180
01181 bool
01182 EcalHitMaker::pulled(const XYZPoint & origin,
01183 const XYZNormal& normal,
01184 XYZPoint & fPoint) const
01185 {
01186
01187 double dotproduct=normal.Dot(fPoint-origin);
01188 if(dotproduct<=0.) return false;
01189
01190
01191 fPoint -= (1+dotproduct)*normal;
01192 return true;
01193 }
01194
01195
01196 void
01197 EcalHitMaker::prepareCrystalNumberArray()
01198 {
01199 for(unsigned iq=0;iq<npadsatdepth_;++iq)
01200 {
01201 if(!validPads_[iq]) continue;
01202 unsigned d1,d2;
01203 convertIntegerCoordinates(padsatdepth_[iq].center().x(),padsatdepth_[iq].center().y(),d1,d2);
01204 myCrystalNumberArray_[d1][d2]=iq;
01205 }
01206 }
01207
01208 void EcalHitMaker::convertIntegerCoordinates(double x, double y,unsigned &ix,unsigned &iy) const
01209 {
01210 int tix=(int)((x-xmin_)/sizex_);
01211 int tiy=(int)((y-ymin_)/sizey_);
01212 ix=iy=9999;
01213 if(tix>=0) ix=(unsigned)tix;
01214 if(tiy>=0) iy=(unsigned)tiy;
01215 }
01216
01217 const std::map<CaloHitID,float>& EcalHitMaker::getHits()
01218 {
01219 if (hitmaphasbeencalculated_) return hitMap_;
01220 for(unsigned ic=0;ic<ncrystals_;++ic)
01221 {
01222
01223 float tof = 0.0;
01224 if(onEcal_==1 || onEcal_==2) tof = (myCalorimeter->getEcalGeometry(onEcal_)->getGeometry(regionOfInterest_[ic].getDetId())->getPosition().mag())/29.98;
01225
01226 if(onEcal_==1){
01227 CaloHitID current_id(EBDetId(regionOfInterest_[ic].getDetId().rawId()).hashedIndex(),tof,0);
01228 hitMap_.insert(std::pair<CaloHitID,float>(current_id,hits_[ic]));
01229 }
01230 else if(onEcal_==2){
01231 CaloHitID current_id(EEDetId(regionOfInterest_[ic].getDetId().rawId()).hashedIndex(),tof,0);
01232 hitMap_.insert(std::pair<CaloHitID,float>(current_id,hits_[ic]));
01233 }
01234 }
01235 hitmaphasbeencalculated_=true;
01236 return hitMap_;
01237 }
01238
01239
01241
01242 void
01243 EcalHitMaker::reorganizePads()
01244 {
01245
01246
01247
01248 crackpadsatdepth_.clear();
01249 crackpadsatdepth_.reserve(etasize_*phisize_);
01250 ncrackpadsatdepth_=0;
01251 std::vector<neighbour> gaps;
01252 std::vector<std::vector<neighbour> > cracks;
01253
01254 cracks.resize(ncrystals_);
01255
01256
01257 for(unsigned iq=0;iq<ncrystals_;++iq)
01258 {
01259 if(!validPads_[iq]) continue;
01260
01261 gaps.clear();
01262
01263
01264 for(unsigned iside=0;iside<4;++iside)
01265 {
01266
01267 CaloDirection thisside=CaloDirectionOperations::Side(iside);
01268 if(regionOfInterest_[iq].crystalNeighbour(iside).toBeGlued())
01269 {
01270
01271 int neighbourstatus=regionOfInterest_[iq].crystalNeighbour(iside).status();
01272 if(neighbourstatus<0)
01273 continue;
01274
01275 unsigned neighbourNumber=regionOfInterest_[iq].crystalNeighbour(iside).number();
01276 if(!validPads_[neighbourNumber]) continue;
01277
01278 if(neighbourstatus==1)
01279 {
01280
01281 cracks[iq].push_back(neighbour(thisside,neighbourNumber));
01282 }
01283 else
01284 {
01285 gaps.push_back(neighbour(thisside,neighbourNumber));
01286 }
01287 }
01288 }
01289
01290 gapsLifting(gaps,iq);
01291 }
01292
01293 unsigned ncracks=cracks.size();
01294
01295 for(unsigned icrack=0;icrack<ncracks;++icrack)
01296 {
01297
01298 cracksPads(cracks[icrack],icrack);
01299 }
01300
01301 }
01302
01303
01304 CLHEP::Hep2Vector &
01305 EcalHitMaker::correspondingEdge(neighbour& myneighbour,CaloDirection dir2 )
01306 {
01307 CaloDirection dir=CaloDirectionOperations::oppositeSide(myneighbour.first);
01308 CaloDirection corner=CaloDirectionOperations::add2d(dir,dir2);
01309
01310 return padsatdepth_[myneighbour.second].edge(corner);
01311 }
01312
01313 bool EcalHitMaker::diagonalEdge(unsigned myPad, CaloDirection dir,CLHEP::Hep2Vector & point)
01314 {
01315 unsigned idir=CaloDirectionOperations::neighbourDirection(dir);
01316 if(regionOfInterest_[myPad].crystalNeighbour(idir).status()<0)
01317 return false;
01318 unsigned nneighbour=regionOfInterest_[myPad].crystalNeighbour(idir).number();
01319 if(!validPads_[nneighbour])
01320 {
01321
01322 return false;
01323 }
01324 point = padsatdepth_[nneighbour].edge(CaloDirectionOperations::oppositeSide(dir));
01325 return true;
01326 }
01327
01328 bool EcalHitMaker::unbalancedDirection(const std::vector<neighbour>& dirs,unsigned & unb,unsigned & dir1, unsigned & dir2)
01329 {
01330 if(dirs.size()==1) return false;
01331 if(dirs.size()%2==0) return false;
01332 CaloDirection tmp;
01333 tmp=CaloDirectionOperations::add2d(dirs[0].first,dirs[1].first);
01334 if(tmp==NONE)
01335 {
01336 unb=2;
01337 dir1=0;
01338 dir2=1;
01339 return true;
01340 }
01341 tmp=CaloDirectionOperations::add2d(dirs[0].first,dirs[2].first);
01342 if(tmp==NONE)
01343 {
01344 unb=1;
01345 dir1=0;
01346 dir2=2;
01347 return true;
01348 }
01349 unb=0;
01350 dir1=1;
01351 dir2=2;
01352 return true;
01353 }
01354
01355
01356 void
01357 EcalHitMaker::gapsLifting(std::vector<neighbour>& gaps,unsigned iq)
01358 {
01359
01360 CrystalPad & myPad = padsatdepth_[iq];
01361 unsigned ngaps=gaps.size();
01362 static bool debug=false;
01363 if(ngaps==1)
01364 {
01365 if(debug)
01366 {
01367 std::cout << " Avant " << ngaps << " " <<gaps[0].first<< std::endl;
01368 std::cout << myPad << std::endl;
01369 }
01370 if(gaps[0].first==NORTH||gaps[0].first==SOUTH)
01371 {
01372 CaloDirection dir1=CaloDirectionOperations::add2d(gaps[0].first,EAST);
01373 CaloDirection dir2=CaloDirectionOperations::add2d(gaps[0].first,WEST);
01374 myPad.edge(dir1)=correspondingEdge(gaps[0],EAST);
01375 myPad.edge(dir2)=correspondingEdge(gaps[0],WEST);
01376 }
01377 else
01378 {
01379 CaloDirection dir1=CaloDirectionOperations::add2d(gaps[0].first,NORTH);
01380 CaloDirection dir2=CaloDirectionOperations::add2d(gaps[0].first,SOUTH);
01381 myPad.edge(dir1)=correspondingEdge(gaps[0],NORTH);
01382 myPad.edge(dir2)=correspondingEdge(gaps[0],SOUTH);
01383 }
01384 if(debug)
01385 {
01386 std::cout << " Apres " << std::endl;
01387 std::cout << myPad << std::endl;
01388 }
01389 }
01390 else
01391 if(ngaps==2)
01392 {
01393 if(debug)
01394 {
01395 std::cout << " Avant " << ngaps << " " <<gaps[0].first<< " " <<gaps[1].first << std::endl;
01396 std::cout << myPad << std::endl;
01397 std::cout << " Voisin 1 " << (gaps[0].second) << std::endl;
01398 std::cout << " Voisin 2 " << (gaps[1].second) << std::endl;
01399 }
01400 CaloDirection corner0=CaloDirectionOperations::add2d(gaps[0].first,gaps[1].first);
01401
01402 CLHEP::Hep2Vector point(0.,0.);
01403 if(corner0!=NONE&&diagonalEdge(iq,corner0,point))
01404 {
01405 CaloDirection corner1=CaloDirectionOperations::add2d(CaloDirectionOperations::oppositeSide(gaps[0].first),gaps[1].first);
01406 CaloDirection corner2=CaloDirectionOperations::add2d(gaps[0].first,CaloDirectionOperations::oppositeSide(gaps[1].first));
01407 myPad.edge(corner0) = point;
01408 myPad.edge(corner1) = correspondingEdge(gaps[1],CaloDirectionOperations::oppositeSide(gaps[0].first));
01409 myPad.edge(corner2) = correspondingEdge(gaps[0],CaloDirectionOperations::oppositeSide(gaps[1].first));
01410 }
01411 else
01412 if(corner0==NONE)
01413 {
01414 if(gaps[0].first==EAST||gaps[0].first==WEST)
01415 {
01416 CaloDirection corner1=CaloDirectionOperations::add2d(gaps[0].first,NORTH);
01417 CaloDirection corner2=CaloDirectionOperations::add2d(gaps[0].first,SOUTH);
01418 myPad.edge(corner1)=correspondingEdge(gaps[0],NORTH);
01419 myPad.edge(corner2)=correspondingEdge(gaps[0],SOUTH);
01420
01421 corner1=CaloDirectionOperations::add2d(gaps[1].first,NORTH);
01422 corner2=CaloDirectionOperations::add2d(gaps[1].first,SOUTH);
01423 myPad.edge(corner1)=correspondingEdge(gaps[1],NORTH);
01424 myPad.edge(corner2)=correspondingEdge(gaps[1],SOUTH);
01425 }
01426 else
01427 {
01428 CaloDirection corner1=CaloDirectionOperations::add2d(gaps[0].first,EAST);
01429 CaloDirection corner2=CaloDirectionOperations::add2d(gaps[0].first,WEST);
01430 myPad.edge(corner1)=correspondingEdge(gaps[0],EAST);
01431 myPad.edge(corner2)=correspondingEdge(gaps[0],WEST);
01432
01433 corner1=CaloDirectionOperations::add2d(gaps[1].first,EAST);
01434 corner2=CaloDirectionOperations::add2d(gaps[1].first,WEST);
01435 myPad.edge(corner1)=correspondingEdge(gaps[1],EAST);
01436 myPad.edge(corner2)=correspondingEdge(gaps[1],WEST);
01437 }
01438 }
01439 if(debug)
01440 {
01441 std::cout << " Apres " << std::endl;
01442 std::cout << myPad << std::endl;
01443 }
01444 }
01445 else
01446 if(ngaps==3)
01447 {
01448
01449 unsigned iubd,idir1,idir2;
01450 CaloDirection diag;
01451 CLHEP::Hep2Vector point(0.,0.);
01452
01453 if(unbalancedDirection(gaps,iubd,idir1,idir2))
01454 {
01455 CaloDirection ubd(gaps[iubd].first),dir1(gaps[idir1].first);
01456 CaloDirection dir2(gaps[idir2].first);
01457
01458
01459
01460 diag=CaloDirectionOperations::add2d(ubd,dir1);
01461 if(diagonalEdge(iq,diag,point))
01462 myPad.edge(diag)=point;
01463 diag=CaloDirectionOperations::add2d(ubd,dir2);
01464 if(diagonalEdge(iq,diag,point))
01465 myPad.edge(diag)=point;
01466 CaloDirection oppside=CaloDirectionOperations::oppositeSide(ubd);
01467 myPad.edge(CaloDirectionOperations::add2d(oppside,dir1))=correspondingEdge(gaps[idir1],oppside);
01468 myPad.edge(CaloDirectionOperations::add2d(oppside,dir2))=correspondingEdge(gaps[idir2],oppside);
01469
01470 }
01471 }
01472 else
01473 if(ngaps==4)
01474 {
01475
01476
01477
01478 CLHEP::Hep2Vector point(0.,0.);
01479 if(diagonalEdge(iq,NORTHEAST,point))
01480 myPad.edge(NORTHEAST)=point;
01481 if(diagonalEdge(iq,NORTHWEST,point))
01482 myPad.edge(NORTHWEST)=point;
01483 if(diagonalEdge(iq,SOUTHWEST,point))
01484 myPad.edge(SOUTHWEST)=point;
01485 if(diagonalEdge(iq,SOUTHEAST,point))
01486 myPad.edge(SOUTHEAST)=point;
01487
01488
01489 }
01490 }
01491
01492 void
01493 EcalHitMaker::cracksPads(std::vector<neighbour> & cracks, unsigned iq)
01494 {
01495
01496 unsigned ncracks=cracks.size();
01497 CrystalPad & myPad = padsatdepth_[iq];
01498 for(unsigned ic=0;ic<ncracks;++ic)
01499 {
01500
01501
01502 switch(cracks[ic].first)
01503 {
01504 case NORTH:
01505 {
01506 mycorners[0] = (padsatdepth_[cracks[ic].second].edge(SOUTHWEST));
01507 mycorners[1] = (padsatdepth_[cracks[ic].second].edge(SOUTHEAST));
01508 mycorners[2] = (myPad.edge(NORTHEAST));
01509 mycorners[3] = (myPad.edge(NORTHWEST));
01510 }
01511 break;
01512 case SOUTH:
01513 {
01514 mycorners[0] = (myPad.edge(SOUTHWEST));
01515 mycorners[1] = (myPad.edge(SOUTHEAST));
01516 mycorners[2] = (padsatdepth_[cracks[ic].second].edge(NORTHEAST));
01517 mycorners[3] = (padsatdepth_[cracks[ic].second].edge(NORTHWEST));
01518 }
01519 break;
01520 case EAST:
01521 {
01522 mycorners[0] = (myPad.edge(NORTHEAST));
01523 mycorners[1] = (padsatdepth_[cracks[ic].second].edge(NORTHWEST));
01524 mycorners[2] = (padsatdepth_[cracks[ic].second].edge(SOUTHWEST));
01525 mycorners[3] = (myPad.edge(SOUTHEAST));
01526 }
01527 break;
01528 case WEST:
01529 {
01530 mycorners[0] = (padsatdepth_[cracks[ic].second].edge(NORTHEAST));
01531 mycorners[1] = (myPad.edge(NORTHWEST));
01532 mycorners[2] = (myPad.edge(SOUTHWEST));
01533 mycorners[3] = (padsatdepth_[cracks[ic].second].edge(SOUTHEAST));
01534 }
01535 break;
01536 default:
01537 {
01538 }
01539 }
01540 CrystalPad crackpad(ic,mycorners);
01541
01542 crackpad.setSurvivalProbability(crackPadProbability_);
01543 crackpadsatdepth_.push_back(crackpad);
01544 }
01545
01546 }
01547
01548
01549 bool EcalHitMaker::inside3D(const std::vector<XYZPoint>& corners,
01550 const XYZPoint& p) const
01551 {
01552
01553
01554
01555
01556 XYZVector crossproduct(0.,0.,0.),previouscrossproduct(0.,0.,0.);
01557
01558 for(unsigned ip=0;ip<4 ; ++ip) {
01559 crossproduct = (corners[ip]-p).Cross(corners[(ip+1)%4]-p);
01560 if(ip==0)
01561 previouscrossproduct=crossproduct;
01562 else
01563 if (crossproduct.Dot(previouscrossproduct)<0.) return false;
01564 }
01565
01566 return true;
01567 }