CMS 3D CMS Logo

EcalHitMaker.cc

Go to the documentation of this file.
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 //#include "Geometry/EcalAlgo/interface/EcalBarrelGeometry.h"
00007 //#include "Geometry/EcalAlgo/interface/EcalEndcapGeometry.h"
00008 //#include "Geometry/CaloGeometry/interface/CaloCellGeometry.h"
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 //#include "FastSimulation/Utilities/interface/Histos.h"
00021 
00022 //#include "Math/GenVector/Transform3D.h"
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   //  myHistos->debug("Constructeur EcalHitMaker");
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   // In some cases, a "dummy" grid, not based on a cell, can be built. The previous variables
00081   // should however be initialized. In such a case onEcal=0
00082   if(!onEcal) return;
00083 
00084   // Same size in eta-phi
00085   etasize_ = size;
00086   phisize_ = size;
00087 
00088   // Build the grid
00089   // The result is put in CellsWindow and is ordered by distance to the pivot
00090   myCalorimeter->getWindow(pivot_.getDetId(),size,size,CellsWindow_);
00091 
00092   buildGeometry();
00093   //  std::cout << " Geometry built " << regionOfInterest_.size() << std::endl;
00094 
00095   truncatedGrid_ = CellsWindow_.size()!=(etasize_*phisize_);
00096 
00097   // A local vector of corners
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 //  std::cout << " Add hit depth called; Current deph is "  << currentdepth_;
00135 //  std::cout << " Required depth is " << depth << std::endl;
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   //  if(cellid.isZero()) std::cout << " cell is Zero " << std::endl;
00143 //  if(xtal<1000) 
00144 //    {
00145 //      std::cout << "Result " << regionOfInterest_[xtal].getX0Back() << " " ;
00146 //      std::cout << depth << std::endl;
00147 //    }
00148 //  myHistos->fill("h5000",depth);
00149   if(xtal<1000)
00150     {
00151       //      myHistos->fill("h5002",regionOfInterest_[xtal].getX0Back(),depth);
00152       //      myHistos->fill("h5003",ecalentrance_.eta(),maxX0_);
00153       if(regionOfInterest_[xtal].getX0Back()>depth) 
00154         {
00155           hits_[xtal]+=spotEnergy;      
00156           //      myHistos->fill("h5005",r);
00157           return true;
00158         }
00159       else
00160         {
00161           rearleakage_+=spotEnergy;
00162         }
00163     }
00164   else
00165     {
00166 //      std::cout << " Return false " << std::endl;
00167 //      std::cout << " Add hit depth called; Current deph is "  << currentdepth_;
00168 //      std::cout << " Required depth is " << depth << std::endl;
00169 //      std::cout << " R = " << r << " " << radiusFactor_ << std::endl; 
00170     }
00171 
00172   outsideWindowEnergy_+=spotEnergy;
00173   return false;
00174 }
00175 
00176 
00177 //bool EcalHitMaker::addHitDepth(double r,double phi,double depth)
00178 //{
00179 //  std::map<unsigned,float>::iterator itcheck=hitMap_.find(pivot_.getDetId().rawId());
00180 //  if(itcheck==hitMap_.end())
00181 //    {
00182 //      hitMap_.insert(std::pair<uint32_t,float>(pivot_.getDetId().rawId(),spotEnergy));
00183 //    }
00184 //  else
00185 //    {
00186 //      itcheck->second+=spotEnergy;
00187 //    }
00188 //  return true;
00189 //}
00190 
00191 bool 
00192 EcalHitMaker::addHit(double r,double phi,unsigned layer)
00193 {
00194   //  std::cout <<" Addhit " << std::endl;
00195   //  std::cout << " Before insideCell " << std::endl;
00196   double sp(1.);
00197   //  std::cout << " Trying to add " << r << " " << phi << " " << radiusFactor_ << std::endl; 
00198   r*=radiusFactor_;
00199   Hep2Vector point(r*std::cos(phi),r*std::sin(phi));
00200   //  std::cout << "point " << point << std::endl;
00201   //  CellID cellid=insideCell(point,sp);
00202   unsigned xtal=fastInsideCell(point,sp);  
00203   //  if(cellid.isZero()) std::cout << " cell is Zero " << std::endl;
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 //  std::cout << " This hit ; r= " << point << " hasn't been added "<<std::endl;
00215 //  std::cout << " Xtal " << xtal << std::endl;
00216 //  for(unsigned ip=0;ip<npadsatdepth_;++ip)
00217 //    {
00218 //      std::cout << padsatdepth_[ip] << std::endl;
00219 //    }
00220   
00221   return false;
00222 }
00223 
00224 // Temporary solution
00225 //bool EcalHitMaker::addHit(double r,double phi,unsigned layer)
00226 //{
00227 //  std::map<unsigned,float>::iterator itcheck=hitMap_.find(pivot_.getDetId().rawId());
00228 //  if(itcheck==hitMap_.end())
00229 //    {
00230 //      hitMap_.insert(std::pair<uint32_t,float>(pivot_.getDetId().rawId(),spotEnergy));
00231 //    }
00232 //  else
00233 //    {
00234 //      itcheck->second+=spotEnergy;
00235 //    }
00236 //  return true;
00237 //}
00238 
00239 
00240 unsigned 
00241 EcalHitMaker::fastInsideCell(const Hep2Vector & point,double & sp,bool debug) 
00242 {
00243 
00244   //  debug = true;
00245   bool found=false;
00246   unsigned niter=0;
00247   // something clever has to be implemented here
00248   unsigned d1,d2;
00249   convertIntegerCoordinates(point.x(),point.y(),d1,d2);
00250   //  std::cout << "Fastinside cell " << point.x() << " " <<  point.y() << " " << d1 << " "<< d2 << " " << nx_ << " " << ny_ << std::endl;
00251   if(d1>=nx_||d2>=ny_) 
00252     {
00253       //      std::cout << " Not in the map " <<std::endl;
00254       return 9999;
00255     }
00256   unsigned cell=myCrystalNumberArray_[d1][d2];
00257   // We are likely to be lucky
00258   //  std::cout << " Got the cell " << cell << std::endl;
00259   if (validPads_[cell]&&padsatdepth_[cell].inside(point)) 
00260     {
00261       //      std::cout << " We are lucky " << cell << std::endl;
00262       sp = padsatdepth_[cell].survivalProbability();
00263       return cell;
00264     }
00265   
00266   //  std::cout << "Starting the loop " << std::endl;
00267   bool status(true);
00268   const std::vector<unsigned>& localCellVector(myCrystalWindowMap_->getCrystalWindow(cell,status));
00269   if(status) 
00270     {
00271       unsigned size=localCellVector.size();      
00272       //      std::cout << " Starting from " << EBDetId(regionOfInterest_[cell].getDetId()) << std::endl;
00273       //      const std::vector<DetId>& neighbours=myCalorimeter->getNeighbours(regionOfInterest_[cell].getDetId());
00274 //      std::cout << " The neighbours are " << std::endl;
00275 //      for(unsigned ic=0;ic<neighbours.size(); ++ic)
00276 //      {
00277 //        std::cout << EBDetId(neighbours[ic]) << std::endl;
00278 //      }
00279 //      std::cout << " Done " << std::endl;
00280       for(unsigned ic=0;ic<8&&ic<size;++ic)
00281         {
00282           unsigned iq=localCellVector[ic];
00283 //        std::cout << " Testing " << EBDetId(regionOfInterest_[iq].getDetId()) << std::endl; ; 
00284 //        std::cout << " " << iq << std::endl;
00285 //        std::cout << padsatdepth_[iq] ;
00286           if(validPads_[iq]&&padsatdepth_[iq].inside(point))
00287             {
00288               //              std::cout << " Yes " << std::endl;
00289               //              myHistos->fill("h1000",niter);
00290               sp = padsatdepth_[iq].survivalProbability();
00291               //              std::cout << "Finished the loop " << niter << std::endl;
00292               //              std::cout << "Inside " << std::endl;
00293               return iq;
00294             }
00295           //      std::cout << " Not inside " << std::endl;
00296           //      std::cout << "No " << std::endl;
00297           ++niter;
00298         }
00299           }
00300   if(debug) std::cout << " not found in a quad, let's check the " << ncrackpadsatdepth_ << " cracks " << std::endl;
00301   //  std::cout << "Finished the loop " << niter << std::endl;
00302   // Let's check the cracks 
00303   //  std::cout << " Let's check the cracks " << ncrackpadsatdepth_ << " " << crackpadsatdepth_.size() << std::endl;
00304   unsigned iquad=0;
00305   unsigned iquadinside=999;
00306   while(iquad<ncrackpadsatdepth_&&!found)
00307     {
00308       //      std::cout << " Inside the while " << std::endl;
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   //  myHistos->fill("h1002",niter);
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   //  myHistos->debug("setTrackParameters");
00330   //  std::cout << " Track " << theTrack << std::endl;
00331   intersections_.clear();
00332   // This is certainly enough
00333   intersections_.reserve(50);
00334   myTrack_=&theTrack;
00335   normal_=normal.Unit();
00336   X0depthoffset_=X0depthoffset;
00337   cellLine(intersections_);
00338   buildSegments(intersections_);
00339 //  std::cout << " Segments " << segments_.size() << std::endl;
00340 //  for(unsigned ii=0; ii<segments_.size() ; ++ii)
00341 //    {
00342 //      std::cout << segments_[ii] << std::endl;
00343 //    }
00344 
00345 
00346   // This is only needed in case of electromagnetic showers 
00347   if(EMSHOWER&&onEcal_&&ecalTotalX0()>0.)
00348     {
00349       //      std::cout << "Total X0  " << ecalTotalX0() << std::endl;
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           // Now calculate the distance in X0 of the back sides of the crystals
00358           // (only for EM showers)
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               // First identify the correct segment
00366               //      std::cout << " Crystal " << ic  << regionOfInterest_[ic].getBackCenter() ;
00367               //      std::cout << " Entrance : " << segments_[ecalFirstSegment_].entrance()<< std::endl;
00368               //      std::cout << " Looking for the segment " << dist << std::endl;
00369               segiterator = find_if(segments_.begin(),segments_.end(),CaloSegment::inSegment(absciss));
00370               //      std::cout << " Done " << std::endl;
00371               if(segiterator==segments_.end() )
00372                 {
00373                   // in this case, we won't have any problem. No need to 
00374                   // calculate the real depth. 
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               //  myHistos->fill("h4000",ecalentrance_.eta(), regionOfInterest_[ic].getX0Back());
00392               //}
00393               //      else
00394               //{
00395               //   // in this case, we won't have any problem. No need to 
00396               //  // calculate the real depth. 
00397               //  regionOfInterest_[ic].setX0Back(9999);
00398               //}
00399             }//EMSHOWER  
00400         } // ndir
00401       //      myHistos->fill("h6000",segments_[ecalFirstSegment_].entrance().eta(),maxX0_);
00402     }
00403   //  std::cout << "Leaving setTrackParameters" << std::endl
00404 }
00405 
00406 
00407 void 
00408 EcalHitMaker::cellLine(std::vector<CaloPoint>& cp) 
00409 {
00410   cp.clear();
00411   //  if(myTrack->onVFcal()!=2)
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   //sort the points by distance (in the ECAL they are not necessarily ordered)
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   // Move the vertex for distance comparison (5cm)
00452   vertex -= 5.*dir;
00453   CaloPoint::DistanceToVertex myDistance(vertex);
00454   sort(cp.begin(),cp.end(),myDistance);
00455   
00456   // The intersections with the HCAL shouldn't need to be sorted
00457   // with the N.I it is actually a source of problems
00458   hcalCellLine(cp);
00459 
00460 //  std::cout << " Intersections ordered by distance to " << vertex << std::endl;
00461 //
00462 //  for (unsigned ic=0;ic<cp.size();++ic)
00463 //    {
00464 //      XYZVector t=cp[ic]-vertex;
00465 //      std::cout << cp[ic] << " " << t.mag() << std::endl;
00466 //    }
00467 }
00468 
00469 
00470 void 
00471 EcalHitMaker::preshowerCellLine(std::vector<CaloPoint>& cp) const
00472 {
00473   //  FSimEvent& mySimEvent = myEventMgr->simSignal();
00474   //  FSimTrack myTrack = mySimEvent.track(fsimtrack_);
00475   //  std::cout << "FsimTrack " << fsimtrack_<< std::endl;
00476   //  std::cout << " On layer 1 " << myTrack.onLayer1() << std::endl;
00477   // std::cout << " preshowerCellLine " << std::endl; 
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           //      std::cout << "Track on ECAL " << myTrack.EcalEntrance_().vertex()*0.1<< std::endl;
00498         }
00499     }
00500 
00501   //  std::cout << " On layer 2 " << myTrack.onLayer2() << std::endl;
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           //      std::cout << "Track on ECAL " << myTrack.EcalEntrance_().vertex()*0.1 << std::endl;
00523         }
00524     }
00525   //  std::cout << " Exit preshower CellLine " << std::endl;
00526 }
00527 
00528 void 
00529 EcalHitMaker::hcalCellLine(std::vector<CaloPoint>& cp) const
00530 {
00531   //  FSimEvent& mySimEvent = myEventMgr->simSignal();
00532   //  FSimTrack myTrack = mySimEvent.track(fsimtrack_);
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       // HCAL thickness in cm (assuming that the particle is coming from 000)
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       // HCAL thickness in cm (assuming that the particle is coming from 000)
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   //  std::vector<XYZPoint> corners;
00571   //  corners.resize(4);
00572   unsigned ic=0;
00573   double t;
00574   XYZPoint xp;
00575   DetId c_entrance,c_exit;
00576   bool entrancefound(false),exitfound(false);
00577   //  std::cout << " Look for intersections " << ncrystals_ << std::endl;
00578   //  std::cout << " regionOfInterest_ " << truncatedGrid_ << " " << regionOfInterest_.size() << std::endl;
00579   // try to determine the number of crystals to test
00580   // First determine the incident angle
00581   double angle=std::acos(normal_.Dot(regionOfInterest_[0].getAxis().Unit()));
00582 
00583   //  std::cout << " Normal " << normal_<< " Axis " << regionOfInterest_[0].getAxis().Unit() << std::endl;
00584   double backdistance=std::sqrt(regionOfInterest_[0].getAxis().mag2())*std::tan(angle);
00585   // 1/2.2cm = 0.45
00586 //   std::cout << " Angle " << angle << std::endl;
00587 //   std::cout << " Back distance " << backdistance << std::endl;
00588   unsigned ncrystals=(unsigned)(backdistance*0.45);
00589   unsigned highlim=(ncrystals+4);
00590   highlim*=highlim;
00591   if(highlim>ncrystals_) highlim=ncrystals_;
00592   //  unsigned lowlim=(ncrystals>2)? (ncrystals-2):0;
00593   //  std::cout << " Ncrys " << ncrystals << std::endl;
00594   
00595   
00596   while(ic<ncrystals_&&(ic<highlim||!exitfound))
00597     {
00598       // Check front side
00599       //      if(!entrancefound)
00600         {
00601           const Plane3D& plan=regionOfInterest_[ic].getFrontPlane();
00602 //        XYZVector axis1=(plan.Normal());
00603 //        XYZVector axis2=regionOfInterest_[ic].getFirstEdge();
00604           xp=intersect(plan,a,b,t,false);
00605           regionOfInterest_[ic].getFrontSide(corners);
00606           //      CrystalPad pad(9999,onEcal_,corners,regionOfInterest_[ic].getCorner(0),axis1,axis2);
00607           //      if(pad.globalinside(xp)) 
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               //      myHistos->fill("j12",highlim,ic);
00614             }
00615         }
00616       
00617       // check rear side
00618         //      if(!exitfound)
00619         {
00620           const Plane3D& plan=regionOfInterest_[ic].getBackPlane();
00621 //        XYZVector axis1=(plan.Normal());
00622 //        XYZVector axis2=regionOfInterest_[ic].getFifthEdge();
00623           xp=intersect(plan,a,b,t,false);
00624           regionOfInterest_[ic].getBackSide(corners);
00625           //      CrystalPad pad(9999,onEcal_,corners,regionOfInterest_[ic].getCorner(4),axis1,axis2);
00626           //      if(pad.globalinside(xp)) 
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               //              std::cout << " Crystal : " << ic << std::endl;
00633               //              myHistos->fill("j10",highlim,ic);
00634             }
00635         }
00636       
00637       if(entrancefound&&exitfound&&c_entrance==c_exit) return;
00638       // check lateral sides 
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 //        XYZVector axis1=(plan.Normal());
00644 //        XYZVector axis2=regionOfInterest_[ic].getLateralEdge(iside);
00645           regionOfInterest_[ic].getLateralSide(iside,corners);
00646           //      CrystalPad pad(9999,onEcal_,corners,regionOfInterest_[ic].getCorner(iside),axis1,axis2);
00647           //      if(pad.globalinside(xp)) 
00648           if(inside3D(corners,xp))
00649             {
00650               cp.push_back(CaloPoint(regionOfInterest_[ic].getDetId(),CaloDirectionOperations::Side(iside),xp)); 
00651               //              std::cout << cp[cp.size()-1] << std::endl;
00652             }     
00653         }
00654       // Go to next crystal 
00655       ++ic;
00656     }    
00657 }
00658 
00659 
00660 void 
00661 EcalHitMaker::buildSegments(const std::vector<CaloPoint>& cp)
00662 {
00663   //  myHistos->debug();
00664   //  TimeMe theT("FamosGrid::buildSegments");
00665   unsigned size=cp.size();
00666   if(size%2!=0) 
00667     {
00668       //      std::cout << " There is a problem " << std::endl;
00669       return;
00670     }
00671   //  myHistos->debug();
00672   unsigned nsegments=size/2;
00673   segments_.reserve(nsegments);
00674   if (size==0) return;
00675   // curv abs
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 //        std::cout << " Problem with the segments " << std::endl;
00690 //        std::cout << cp[2*is].whichDetector() << " " << cp[2*is+1].whichDetector() << std::endl;
00691 //        std::cout << is << " " <<cp[2*is].getDetId().rawId() << std::endl; 
00692 //        std::cout << (2*is+1) << " " <<cp[2*is+1].getDetId().rawId() << std::endl; 
00693           ++is;
00694           continue;
00695         }
00696 
00697       // Check if it is a Preshower segment - Layer 1 
00698       // One segment per layer, nothing between
00699       //      myHistos->debug("Just avant Preshower"); 
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               //              std::cout << " Added (1-1)" << preshsegment << std::endl;
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       // Check if it is a Preshower segment - Layer 2 
00723       // One segment per layer, nothing between
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               //              std::cout << " Added (1-2)" << preshsegment << std::endl;
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       // Now deal with the ECAL
00747       // One segment in each crystal. Segment corresponding to cracks/gaps are added
00748       //      myHistos->debug("Just avant ECAL"); 
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               // set the real entrance
00755               if (ecalFirstSegment_<0) ecalFirstSegment_=segments_.size();
00756 
00757               // !! Approximatiom : the first segment is always in a crystal
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                  // std::cout << " Added (2)" << segment << std::endl;
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               // Now check if a gap or crack should be added
00777               if(is<nsegments)
00778                 {                 
00779                   DetId cell3=cp[2*is].getDetId();
00780                   if(cp[2*is].whichDetector()!=DetId::Hcal) 
00781                     {
00782                       // Crack inside the ECAL
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                       //   std::cout <<" Added(3) "<< cracksegment << std::endl;
00792                     }
00793                   else
00794                     {
00795                       // a segment corresponding to ECAL/HCAL transition should be
00796                       // added here
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       //      myHistos->debug("Just avant HCAL"); 
00817       // HCAL
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           //      std::cout <<" Added(4) "<< segment << std::endl;
00828           ++is; 
00829         }
00830     }
00831 //  std::cout << " PS1 " << X0PS1_ << " " << L0PS1_ << std::endl;
00832 //  std::cout << " PS2 " << X0PS2_ << " " << L0PS2_ << std::endl;
00833 //  std::cout << " ECAL " << X0ECAL_ << " " << L0ECAL_ << std::endl;
00834 //  std::cout << " HCAL " << X0HCAL_ << " " << L0HCAL_ << std::endl;
00835   
00836   totalX0_ = X0PS1_+X0PS2_+X0ECAL_+X0EHGAP_+X0HCAL_;
00837   totalL0_ = L0PS1_+L0PS2_+L0ECAL_+L0EHGAP_+L0HCAL_;
00838   //  myHistos->debug("Just avant le fill"); 
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 //  if(X0ECAL_<1.) 
00846 //    {
00847 //      for(unsigned ii=0; ii<segments_.size() ; ++ii)
00848 //      {
00849 //        std::cout << segments_[ii] << std::endl;
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   //  std::cout << " Finished the segments " << std::endl;
00861     
00862 }
00863 
00864 void 
00865 EcalHitMaker::buildGeometry()
00866 {
00867   configuredGeometry_ = false;
00868   ncrystals_ = CellsWindow_.size();
00869   // create the vector with of pads with the appropriate size
00870   padsatdepth_.resize(ncrystals_);
00871   
00872   // This is fully correct in the barrel. 
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   // Computes the map of the neighbours
00895   myCrystalWindowMap_ = new CrystalWindowMap(myCalorimeter,regionOfInterest_);
00896 }
00897 
00898 
00899 
00900 // depth is in X0 
00901 bool 
00902 EcalHitMaker::getPads(double depth) 
00903 {
00904   //std::cout << " New depth " << depth << std::endl;
00905   // The first time, the relationship between crystals must be calculated
00906   // but only in the case of EM showers
00907 
00908   if(EMSHOWER && !configuredGeometry_) configureGeometry();
00909 
00910 
00911   radiusFactor_ = (EMSHOWER) ? moliereRadius*radiusCorrectionFactor_:interactionLength;
00912   detailedShowerTail_ = false;
00913   currentdepth_ = depth+X0depthoffset_;
00914   
00915 //  if(currentdepth_>maxX0_+ps1TotalX0()+ps2TotalX0()) 
00916 //    {
00917 //      currentdepth_=maxX0_+ps1TotalX0()+ps2TotalX0()-1.; // the -1 is for safety
00918 //      detailedShowerTail_=true;
00919 //    }
00920     
00921 //  std::cout << " FamosGrid::getQuads " << currentdepth_ << " " << maxX0_ << std::endl;
00922 
00923   ncrackpadsatdepth_=0;
00924   
00925   xmin_=ymin_=999;
00926   xmax_=ymax_=-999;
00927   double locxmin,locxmax,locymin,locymax;
00928 
00929   // Get the depth of the pivot
00930   std::vector<CaloSegment>::const_iterator segiterator;
00931   // First identify the correct segment
00932   // EM shower 
00933   if(EMSHOWER)
00934     segiterator = find_if(segments_.begin(),segments_.end(),CaloSegment::inX0Segment(currentdepth_));
00935   
00936   //Hadron shower 
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   //  std::cout << *segiterator << std::endl;
00948   
00949   if(segiterator->whichDetector()!=DetId::Ecal)
00950     {
00951       std::cout << " In  " << segiterator->whichDetector() << std::endl;
00952       //      buildPreshower();
00953       return false;
00954     }
00955   
00956   //  std::cout << *segiterator << std::endl;
00957   // get the position of the origin
00958   
00959   XYZPoint origin;
00960   if(EMSHOWER)
00961     origin=segiterator->positionAtDepthinX0(currentdepth_);
00962   if(HADSHOWER)
00963     origin=segiterator->positionAtDepthinL0(currentdepth_);
00964 
00965   //  std::cout << " currentdepth_ " << currentdepth_ << " " << origin << std::endl;
00966   XYZVector newaxis=pivot_.getFirstEdge().Cross(normal_);
00967 
00968 //  std::cout  << "Normal " << normal_ << std::endl;
00969 //  std::cout << " New axis " << newaxis << std::endl;
00970 
00971 //  std::cout << " ncrystals  " << ncrystals << std::endl;
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       //      std::cout << " Building geometry for " << regionOfInterest_[ic].getCellID() << std::endl;
00981       XYZPoint a,b;
00982 
00983       //      std::cout << " Origin " << origin << std::endl;
00984 
00985       //      std::vector<XYZPoint> corners;
00986       //      corners.reserve(4);
00987       double dummyt;
00988       bool hasbeenpulled=false;
00989       bool behindback=false;
00990       for(unsigned il=0;il<4;++il)
00991         {
00992           // a is the il-th front corner of the crystal. b is the corresponding rear corner
00993           regionOfInterest_[ic].getLateralEdges(il,a,b);
00994           
00995           // pull the surface if necessary (only in the front of the crystals) 
00996           XYZPoint aprime=a;
00997           if(pulled(origin,normal_,a)) 
00998             {
00999               b=aprime;
01000               hasbeenpulled=true;
01001             }
01002           
01003           // compute the intersection. 
01004           // Check that the intersection is in the [a,b] segment  if HADSHOWER
01005           // if EMSHOWER the intersection is calculated as if the crystals were infinite
01006           XYZPoint xx=(EMSHOWER)?intersect(plan_,a,b,dummyt,false):intersect(plan_,a,b,dummyt,true);
01007           
01008           if(dummyt>1) behindback=true;
01009           //      std::cout << " Intersect " << il << " " << a << " " << b << " " << plan_ << " " << xx << std::endl;
01010           // check that the intersection actually exists 
01011           if(xx.mag2()!=0)
01012             {
01013               corners[il] = xx;
01014             }     
01015         }    
01016       //      std::cout << " ncorners " << corners.size() << std::endl;
01017       if(behindback&&EMSHOWER) detailedShowerTail_=true;
01018       // If the quad is completly defined. Store it ! 
01019       if(corners.size()==4)
01020         {
01021           padsatdepth_[ic]=CrystalPad(ic,corners,trans,bfactor_);
01022           // Parameter to be tuned
01023           if(hasbeenpulled) padsatdepth_[ic].setSurvivalProbability(pulledPadProbability_);
01024           validPads_[ic]=true;
01025           ++nquads;     
01026           // In principle, this should be done after the quads reorganization. But it would cost one more loop
01027           //  quadsatdepth_[ic].extrems(locxmin,locxmax,locymin,locymax);
01028           //  if(locxmin<xmin_) xmin_=locxmin;
01029           //  if(locymin<ymin_) ymin_=locymin;
01030           //  if(locxmax>xmax_) xmax_=locxmax;
01031           //  if(locymax>ymax_) ymax_=locymax;
01032         }
01033       else
01034         {
01035           padsatdepth_[ic]=CrystalPad();
01036           validPads_[ic]=false;
01037         }
01038     }
01039   //  std::cout << " Number of quads " << quadsatdepth_.size() << std::endl; 
01040   if(doreorg_)reorganizePads();
01041   //  std::cout << "Finished to reorganize " << std::endl;
01042   npadsatdepth_=nquads;
01043   //  std::cout << " prepareCellIDMap " << std::endl;
01044   
01045 
01046   // Resize the Quads to allow for some numerical inaccuracy 
01047   // in the "inside" function
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   // Make sure that sizex_ and sizey_ are set before running prepareCellIDMap
01067   prepareCrystalNumberArray();
01068 
01069   //  std::cout << " Finished  prepareCellIDMap " << std::endl;
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       //      std::cout << " Building " << cellids_[ic] << std::endl;
01085       for(unsigned idir=0;idir<8;++idir)
01086         {
01087 
01088           unsigned oppdir=CaloDirectionOperations::oppositeDirection(idir);
01089           // Is there something else to do ? 
01090           // The relationship with the neighbour may have been set previously.
01091           if(regionOfInterest_[ic].crystalNeighbour(idir).status()>=0) 
01092             {
01093               //              std::cout << " Nothing to do " << std::endl;
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               // no neighbour in this direction
01103               regionOfInterest_[ic].crystalNeighbour(idir).setStatus(-1);
01104               continue;
01105             }
01106           // Determine the number of this neighbour
01107           //      std::cout << " The neighbour is " << newcell << std::endl;
01108           std::map<DetId,unsigned>::const_iterator niter(DetIdMap_.find(newcell));
01109           if(niter==DetIdMap_.end())
01110             {
01111               //              std::cout << " The neighbour is not in the map " << std::endl;
01112               regionOfInterest_[ic].crystalNeighbour(idir).setStatus(-1);
01113               continue;
01114             }
01115           // Now there is a neighbour     
01116           //      std::cout << " The neighbour is " << niter->second << " " << cellids_[niter->second] << std::endl;
01117           regionOfInterest_[ic].crystalNeighbour(idir).setNumber(niter->second);
01118           //      std::cout << " Managed to set crystalNeighbour " << ic << " " << idir << std::endl;
01119           //      std::cout << " Trying  " << niter->second << " " << oppdir << std::endl;
01120           regionOfInterest_[niter->second].crystalNeighbour(oppdir).setNumber(ic);
01121           //      std::cout << " Crack/gap " << std::endl;
01122           if(myCalorimeter->borderCrossing(oldcell,newcell))
01123             {
01124               regionOfInterest_[ic].crystalNeighbour(idir).setStatus(1);
01125               regionOfInterest_[niter->second].crystalNeighbour(oppdir).setStatus(1);
01126               //              std::cout << " Crack ! " << std::endl;
01127             }
01128           else
01129             {
01130               regionOfInterest_[ic].crystalNeighbour(idir).setStatus(0);
01131               regionOfInterest_[niter->second].crystalNeighbour(oppdir).setStatus(0);
01132               //              std::cout << " Gap" << std::endl;
01133             }       
01134         }
01135     }
01136     // Magnetic field a la Charlot
01137   double theta=EcalEntrance_.theta();
01138   if(theta>M_PI_2) theta=M_PI-theta;
01139   bfactor_=1./(1.+0.133*theta);
01140   // the effect of the magnetic field in the EC is currently ignored 
01141   if(myCalorimeter->magneticField()==0. || !central_) bfactor_=1.;
01142 }
01143 
01144 // project fPoint on the plane (original,normal)
01145 bool 
01146 EcalHitMaker::pulled(const XYZPoint & origin, 
01147                      const XYZNormal& normal, 
01148                      XYZPoint & fPoint) const 
01149 {
01150   // check if fPoint is behind the origin
01151   double dotproduct=normal.Dot(fPoint-origin);
01152   if(dotproduct<=0.) return false;
01153 
01154   //norm of normal is 1 
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   // Some cleaning first 
01200   //  std::cout << " Starting reorganize " << std::endl;
01201   crackpadsatdepth_.clear();
01202   crackpadsatdepth_.reserve(etasize_*phisize_);
01203   ncrackpadsatdepth_=0;
01204   std::vector<neighbour> gaps;
01205   std::vector<std::vector<neighbour> > cracks;  
01206   //  cracks.clear();
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       //   std::cout << padsatdepth_[iq] << std::endl;
01216       //check all the directions
01217       for(unsigned iside=0;iside<4;++iside)
01218         {
01219           //      std::cout << " To be glued " << iside << " " << regionOfInterest_[iq].crystalNeighbour(iside).toBeGlued() << std::endl;
01220           CaloDirection thisside=CaloDirectionOperations::Side(iside);
01221           if(regionOfInterest_[iq].crystalNeighbour(iside).toBeGlued())
01222             {
01223               // look for the neighbour and check that it exists
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               // there is a crack between 
01231               if(neighbourstatus==1)
01232                 {
01233                   //              std::cout << " 1 Crack : " << thisside << " " << cellids_[iq]<< " " << cellids_[neighbourNumber] << std::endl;
01234                   cracks[iq].push_back(neighbour(thisside,neighbourNumber));
01235                 } // else it is a gap 
01236               else
01237                 {
01238                   gaps.push_back(neighbour(thisside,neighbourNumber));
01239                 }
01240             }
01241         }
01242       // Now lift the gaps
01243       gapsLifting(gaps,iq);
01244     }
01245 
01246   unsigned ncracks=cracks.size();
01247   //  std::cout << " Cracks treatment : " << cracks.size() << std::endl;
01248   for(unsigned icrack=0;icrack<ncracks;++icrack)
01249     {
01250       //      std::cout << " Crack number " << crackiter->first << std::endl;
01251       cracksPads(cracks[icrack],icrack);
01252     }
01253 
01254 }
01255 
01256 //dir 2 = N,E,W,S
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   //  std::cout << "Corresponding Edge " << dir<< " " << dir2 << " " << corner << std::endl;
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       //      std::cout << " Wasn't able to move " << std::endl;
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   //  std::cout << " Entering gapsLifting "  << std::endl;
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           // in this case the four corners have to be changed 
01402           unsigned iubd,idir1,idir2;
01403           CaloDirection diag;
01404           Hep2Vector point(0.,0.);
01405           //      std::cout << " Yes : 3 gaps" << std::endl;
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               //              std::cout << " Avant " << std::endl << myPad << std::endl;
01412               //              std::cout << ubd << " " << dir1 << " " << dir2 << std::endl;
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               //              std::cout << " Apres " << std::endl << myPad << std::endl;
01423             }                         
01424         }
01425       else
01426         if(ngaps==4)
01427           {
01428             //      std::cout << " Waouh :4 gaps" << std::endl;
01429             //      std::cout << " Avant " << std::endl;
01430             //      std::cout << myPad<< std::endl;
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             //      std::cout << " Apres " << std::endl;
01441             //      std::cout << myPad<< std::endl;
01442           }   
01443 }
01444 
01445 void 
01446 EcalHitMaker::cracksPads(std::vector<neighbour> & cracks, unsigned iq)
01447 {
01448   //  std::cout << " myPad " << &myPad << std::endl;
01449   unsigned ncracks=cracks.size();
01450   CrystalPad & myPad = padsatdepth_[iq];
01451   for(unsigned ic=0;ic<ncracks;++ic)
01452     {
01453       //      std::vector<Hep2Vector> mycorners;
01454       //      mycorners.reserve(4);
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       // to be tuned. A simpleconfigurable should be used
01495       crackpad.setSurvivalProbability(crackPadProbability_);   
01496       crackpadsatdepth_.push_back(crackpad);
01497     }
01498   //  std::cout << " Finished cracksPads " << std::endl;
01499 }
01500 
01501 
01502 bool EcalHitMaker::inside3D(const std::vector<XYZPoint>& corners, 
01503                             const XYZPoint& p) const
01504 {
01505   // corners and p are in the same plane
01506   // p is inside "corners" if the four crossproducts (corners[i]xcorners[i+1]) 
01507   // are in the same direction
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 }

Generated on Tue Jun 9 17:35:02 2009 for CMSSW by  doxygen 1.5.4