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