All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups
ComputeShowerShapesProcessor.cc
Go to the documentation of this file.
1 #include <cmath>
2 #include <gsl/gsl_sf_gamma.h>
3 #include <vector>
4 
5 #include <marlin/Global.h>
6 #include <GeometryUtil.h>
7 
8 #include <DD4hep/DD4hepUnits.h>
9 #include <DD4hep/DetType.h>
10 #include <DD4hep/DetectorSelector.h>
11 #include <DD4hep/Detector.h>
12 #include <DDRec/DetectorData.h>
13 
14 #include "EVENT/ReconstructedParticle.h"
15 #include "IMPL/ClusterImpl.h"
16 #include <lcio.h>
17 
18 #include "CalorimeterHitType.h"
19 
20 //#include "Api/PandoraApi.h"
21 
22 #include "TVector3.h"
23 
25 
27 
29  : Processor("ComputeShowerShapesProcessor") {
30 
31  // Processor description
32  _description = "Cluster Shower Profile extraction using Fitting" ;
33  registerInputCollection( LCIO::RECONSTRUCTEDPARTICLE,
34  "PFOCollection",
35  "PFO collection name",
37  std::string("PandoraPFOs"));
38 
39  registerProcessorParameter("ClusterCollectionName",
40  "Cluster collection name",
42  std::string("PandoraClusters"));
43 
44  registerProcessorParameter("RadiationLength_Ecal",
45  "RadiationLength of Absorbers",
46  _X01,
47  float(3.50));
48 
49  registerProcessorParameter("RadiationLength_Hcal",
50  "RadiationLength of Absorbers",
51  _X02,
52  float(17.57));
53 
54  registerProcessorParameter("MoliereRadius_Ecal",
55  "Moliere radius of Absorbers",
56  _Rm1,
57  float(9.00));
58 
59  registerProcessorParameter("MoliereRadius_Hcal",
60  "Moliere radius of Absorbers",
61  _Rm2,
62  float(17.19));
63 
64 }
65 
66 void ComputeShowerShapesProcessor::init( LCEvent * evt ) {
67  streamlog_out(DEBUG) << " init called " << std::endl ;
68 
69  _PFOCol = evt->getCollection( _ClusterCollection ) ;
70  //_myShowerShapes = new ComputeShowerShapes();
71  //define variable names
72  std::vector<std::string> ClusterShapeNames;
73  ClusterShapeNames.push_back("chi2");
74  ClusterShapeNames.push_back("max_Ed");
75  ClusterShapeNames.push_back("showerMax");
76  ClusterShapeNames.push_back("absorption_Length");
77  ClusterShapeNames.push_back("showerMax_photon");
78  ClusterShapeNames.push_back("showerMax_ratio");
79  ClusterShapeNames.push_back("Rm");
80  ClusterShapeNames.push_back("showerstart");
81  ClusterShapeNames.push_back("functionstart");
82  ClusterShapeNames.push_back("a");
83  ClusterShapeNames.push_back("b");
84  ClusterShapeNames.push_back("c");
85  ClusterShapeNames.push_back("d");
86  ClusterShapeNames.push_back("max_Ed_hit");
87  ClusterShapeNames.push_back("showerMax_hit");
88  ClusterShapeNames.push_back("xt90");
89  ClusterShapeNames.push_back("xl20");
90  ClusterShapeNames.push_back("depth_of_cluster");
91  ClusterShapeNames.push_back("meanOf_hitradius");
92  ClusterShapeNames.push_back("rmsOf_hitradius");
93  // ClusterShapeNames.push_back("Eclus_over_Ptrue");
94 
95  _PFOCol->parameters().setValues("ClusterShapeParameters",ClusterShapeNames);
96 
97  printParameters();
98 
99 }
100 
102 }
103 
105  _PFOCol = evt->getCollection( _PfoCollection ) ;
106  int nClusters = _PFOCol->getNumberOfElements();
107 
108  const unsigned int ecal_Index(0) ;
109  const unsigned int hcal_Index(1) ;
110  const unsigned int yoke_Index(2) ;
111  const unsigned int lcal_Index(3) ;
112  const unsigned int lhcal_Index(4);
113  const unsigned int bcal_Index(5) ;
114 
115  for (int iClu=0;iClu<nClusters;++iClu) {
116  ReconstructedParticle* part=(ReconstructedParticle*) _PFOCol->getElementAt( iClu );
117 
118  for(unsigned int jClu=0;jClu<part->getClusters().size();jClu++){
119  ClusterImpl* pCluster = (ClusterImpl*) part->getClusters()[jClu]; //only use first cluster shape
120 
121  const unsigned int nHitsInCluster(pCluster->getCalorimeterHits().size());
122 
123  float clusterEnergy(0.);
124  float *pHitE = new float[nHitsInCluster];
125  float *pHitX = new float[nHitsInCluster];
126  float *pHitY = new float[nHitsInCluster];
127  float *pHitZ = new float[nHitsInCluster];
128  int *typ = new int[nHitsInCluster];
129 
130  for (unsigned int iHit = 0; iHit < nHitsInCluster; ++iHit)
131  {
132  EVENT::CalorimeterHit *pCalorimeterHit = (CalorimeterHit*)(pCluster->getCalorimeterHits()[iHit]);
133 
134  const float caloHitEnergy(pCalorimeterHit->getEnergy());
135 
136  pHitE[iHit] = caloHitEnergy;
137  pHitX[iHit] = pCalorimeterHit->getPosition()[0];
138  pHitY[iHit] = pCalorimeterHit->getPosition()[1];
139  pHitZ[iHit] = pCalorimeterHit->getPosition()[2];
140  clusterEnergy += caloHitEnergy;
141 
142  switch (CHT(pCalorimeterHit->getType()).caloID())
143  {
144  case CHT::ecal: typ[iHit]=ecal_Index; break;
145  case CHT::hcal: typ[iHit]=hcal_Index; break;
146  case CHT::yoke: typ[iHit]=yoke_Index; break;
147  case CHT::lcal: typ[iHit]=lcal_Index; break;
148  case CHT::lhcal: typ[iHit]=lhcal_Index; break;
149  case CHT::bcal: typ[iHit]=bcal_Index; break;
150  default: streamlog_out(DEBUG) << " no subdetector found for hit with type: " << pCalorimeterHit->getType() << std::endl;
151  }
152  }
153 
154  pClusterShapes = new ClusterShapes(nHitsInCluster, pHitE, pHitX, pHitY, pHitZ);
155  pClusterShapes->setHitTypes(typ); //set hit types
156 
157  //here is cluster shape study - cluster transverse & longitudinal information
158  //define variables
159  float chi2,a,b,c,d,xl0,CoG[3],xStart[3]; //for fitting parameters
160  float X0[2]={0,0}; //in mm. //this is the exact value of tangsten and iron
161  float Rm[2]={0,0}; //in mm. need to change to estimate correctly times 2
162  X0[0]=_X01;
163  X0[1]=_X02;
164  Rm[0]=_Rm1;
165  Rm[1]=_Rm2;
166 
167  //get barrel detector surfce
168  //Get ECal Barrel extension by type, ignore plugs and rings
169  const dd4hep::rec::LayeredCalorimeterData * eCalBarrelExtension= MarlinUtil::getLayeredCalorimeterData( ( dd4hep::DetType::CALORIMETER | dd4hep::DetType::ELECTROMAGNETIC | dd4hep::DetType::BARREL),
170  ( dd4hep::DetType::AUXILIARY | dd4hep::DetType::FORWARD ) );
171  float ecalrad = eCalBarrelExtension->extent[0]/dd4hep::mm;
172 
173  //get endcap detector surfce
174  //Get ECal Endcap extension by type, ignore plugs and rings
175  const dd4hep::rec::LayeredCalorimeterData * eCalEndcapExtension= MarlinUtil::getLayeredCalorimeterData( ( dd4hep::DetType::CALORIMETER | dd4hep::DetType::ELECTROMAGNETIC | dd4hep::DetType::ENDCAP),
176  ( dd4hep::DetType::AUXILIARY | dd4hep::DetType::FORWARD ) );
177  float plugz = eCalEndcapExtension->extent[2]/dd4hep::mm;
178 
179  //looking for the hit which corresponds to the nearest hit from IP in the direction of the center of gravity
180  int index_xStart=0;
181  float lCoG=0.0,tmpcos=0.0,tmpsin=0.0,detsurface=0.0;
182  CoG[0]=pClusterShapes->getEigenVecInertia()[0];
183  CoG[1]=pClusterShapes->getEigenVecInertia()[1];
184  CoG[2]=pClusterShapes->getEigenVecInertia()[2];
185  //CoG2[0]=pCluster->getPosition()[0];
186  //CoG2[1]=pCluster->getPosition()[1];
187  //CoG2[2]=pCluster->getPosition()[2];
188 
189  lCoG=sqrt(CoG[0]*CoG[0]+CoG[1]*CoG[1]+CoG[2]*CoG[2]);
190  tmpcos=CoG[2]/lCoG;
191  tmpsin=sqrt(CoG[0]*CoG[0]+CoG[1]*CoG[1])/lCoG;
192  pClusterShapes->fit3DProfile(chi2,a,b,c,d,xl0,xStart,index_xStart,X0,Rm); //is this good??
193  float lxstart=sqrt(xStart[0]*xStart[0]+xStart[1]*xStart[1]);
194  //calculate detector surface
195  if(fabs(xStart[2])<plugz){ //if in the barrel
196  detsurface=(lxstart-ecalrad)/tmpsin;
197  }else{ //if in plug
198  detsurface=(fabs(xStart[2])-plugz)/fabs(tmpcos);
199  }
200 
201  //float maxed=a*pow(b/c,b)*exp(-b); //for simple fitting
202  float maxed = a*c*gsl_sf_gammainv(b)*pow(b-1,b-1)*exp(-b+1); //for advanced multiply with fabs(d) to avoid NaN
203  float maxlength_pho=(1.0*std::log(clusterEnergy/(X0[0] * 0.021/Rm[0]))-0.5); //this definition, +0.5 if gamma
204 
205  TVector3 clusdirection(CoG[0]-xStart[0],CoG[1]-xStart[1],CoG[2]-xStart[2]);
206 
207 
208  EVENT::FloatVec shapes;
209  //these variables are fit based variables
210  shapes.push_back(chi2);
211  shapes.push_back(maxed);
212  shapes.push_back(((b-1.0)*X0[0]/c+xl0+detsurface)/(2.0*X0[0]));
213  shapes.push_back(1/fabs(d));
214  shapes.push_back(maxlength_pho);
215  shapes.push_back(((b-1.0)/c)/maxlength_pho);
216  shapes.push_back(Rm[0]*2.0);
217  shapes.push_back(detsurface);
218  shapes.push_back(xl0);
219  shapes.push_back(a);
220  shapes.push_back(b);
221  shapes.push_back(c);
222  shapes.push_back(d);
223  //these variables are detector based variables
224  shapes.push_back(pClusterShapes->getEmax(xStart,index_xStart,X0,Rm));
225  shapes.push_back(pClusterShapes->getsmax(xStart,index_xStart,X0,Rm));
226  shapes.push_back(pClusterShapes->getxt90(xStart,index_xStart,X0,Rm));
227  shapes.push_back(pClusterShapes->getxl20(xStart,index_xStart,X0,Rm));
228 
229  //20150708 add variables by Hale
230  shapes.push_back(clusdirection.Mag()); // depth of the cluster
231  shapes.push_back(pClusterShapes->getRhitMean(xStart,index_xStart,X0,Rm)); // mean of the radius of the hits wrt cog
232  shapes.push_back(pClusterShapes->getRhitRMS(xStart,index_xStart,X0,Rm)); // RMS of the radius of the hits wrt cog
233 
234  //add shower shapes
235  pCluster->setShape(shapes);
236 
237  delete pClusterShapes;
238  delete[] pHitE; delete[] pHitX; delete[] pHitY; delete[] pHitZ;
239  }
240  }
241 }
242 
243 void ComputeShowerShapesProcessor::check( LCEvent * /*evt*/ ) {
244 }
245 
247  //delete _myShowerShapes;
248 }
249 
static const float mm
virtual void processRunHeader(LCRunHeader *run)
ComputeShowerShapesProcessor aComputeShowerShapesProcessor