All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups
VTXDigiProcessor.cc
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 #include "VTXDigiProcessor.h"
3 #include <iostream>
4 
5 #include <EVENT/LCCollection.h>
6 #include <IMPL/LCCollectionVec.h>
7 #include <EVENT/SimTrackerHit.h>
8 #include <IMPL/TrackerHitImpl.h>
9 #include <EVENT/MCParticle.h>
10 // #include "random.h"
11 // #include <CLHEP/Random/RandGauss.h>
12 #include <gsl/gsl_randist.h>
13 #include "marlin/ProcessorEventSeeder.h"
14 
15 
16 #include "CLHEP/Vector/TwoVector.h"
17 
18 #include <cmath>
19 #include <algorithm>
20 #include <sstream>
21 
22 using namespace lcio ;
23 using namespace marlin ;
24 using namespace std ;
25 
27 
28 
29 VTXDigiProcessor::VTXDigiProcessor() : Processor("VTXDigiProcessor") {
30 
31  // modify processor description
32  _description = "VTXDigiProcessor should create VTX TrackerHits from SimTrackerHits" ;
33 
34 
35  // register steering parameters: name, description, class-variable, default value
36 
37  registerProcessorParameter( "SmearAlongLadders" ,
38  "Points smeared along the ladders" ,
40  int(1)) ;
41 
42  registerProcessorParameter( "PointResolutionRPhi_VTX" ,
43  "R-Phi Resolution in VTX" ,
45  float(0.0040)) ;
46 
47  registerProcessorParameter( "PointResolutionZ_VTX" ,
48  "Z Resolution in VTX" ,
50  float(0.0040));
51 
52  registerProcessorParameter( "PointResolutionRPhi_SIT" ,
53  "R-Phi Resolution in SIT" ,
55  float(0.010)) ;
56 
57  registerProcessorParameter( "PointResolutionZ_SIT" ,
58  "Z Resolution in SIT" ,
60  float(0.010));
61 
62  registerProcessorParameter( "PointResolutionRPhi_SET" ,
63  "R-Phi Resolution in SET" ,
65  float(0.010)) ;
66 
67  registerProcessorParameter( "PointResolutionZ_SET" ,
68  "Z Resolution in SET" ,
70  float(0.010));
71 
72  std::vector<int> activeSETLayers ;
73  activeSETLayers.push_back( 1 ) ;
74 
75  registerProcessorParameter( "ActiveSETLayers",
76  "only SET hits from active layers are digitized (mimic stereo layers)",
78  activeSETLayers );
79 
80  registerProcessorParameter( "RemoveDrays" ,
81  "Remove D-rays ?",
83  int(0));
84 
85  registerProcessorParameter( "MomentumCutForDRays" ,
86  "Momentum Cut For D Rays (MeV)",
87  _momCut ,
88  float(10.0));
89 
90  registerProcessorParameter( "Debug",
91  "Debugging option",
92  _debug,
93  int(0));
94 
95 
96  FloatVec effDefault(6) ;
97  for(int i=0 ;i<6; i++ )
98  effDefault[i] = 1.0 ;
99 
100 
101  registerProcessorParameter( "HitEfficiencyPerLayer_VTX" ,
102  "hit efficiencies per VXD layer (default: 1.0)" ,
103  _vxdEff ,
104  effDefault ) ;
105 
106 
107  // Input collections
108  registerInputCollection( LCIO::SIMTRACKERHIT,
109  "VTXCollectionName" ,
110  "Name of the VTX SimTrackerHit collection" ,
111  _colNameVTX ,
112  std::string("VXDCollection") ) ;
113 
114  registerInputCollection( LCIO::SIMTRACKERHIT,
115  "SITCollectionName" ,
116  "Name of the SIT SimTrackerHit collection" ,
117  _colNameSIT ,
118  std::string("SITCollection") ) ;
119 
120  registerInputCollection( LCIO::SIMTRACKERHIT,
121  "SETCollectionName" ,
122  "Name of the SET SimTrackerHit collection" ,
123  _colNameSET ,
124  std::string("SETCollection") ) ;
125 
126  // Output collections
127  registerOutputCollection( LCIO::TRACKERHIT,
128  "VTXHitCollection" ,
129  "Name of the vxd TrackerHit output collection" ,
131  std::string("VTXTrackerHits") ) ;
132 
133  registerOutputCollection( LCIO::TRACKERHIT,
134  "SITHitCollection" ,
135  "Name of the sit TrackerHit output collection" ,
137  std::string("SITTrackerHits") ) ;
138 
139  registerOutputCollection( LCIO::TRACKERHIT,
140  "SETHitCollection" ,
141  "Name of the set TrackerHit output collection" ,
143  std::string("SETTrackerHits") ) ;
144 
145 }
146 
147 
149 
150  // usually a good idea to
151  printParameters() ;
152 
153  _nRun = 0 ;
154  _nEvt = 0 ;
155 
156  // initialize gsl random generator
157  _rng = gsl_rng_alloc(gsl_rng_ranlxs2);
158  Global::EVENTSEEDER->registerProcessor(this);
159 
160  // check that we have the efficiencies for all layers
161  const gear::VXDParameters& gearVXD = Global::GEAR->getVXDParameters() ;
162  const gear::VXDLayerLayout& layerVXD = gearVXD.getVXDLayerLayout();
163  const unsigned int nLayer = layerVXD.getNLayers() ;
164 
165  if( _vxdEff.size() < nLayer ){
166 
167  std::stringstream s ;
168  s << " VTXDigiProcessor::init - wrong number of VXD efficiencies given : " << _vxdEff.size()
169  << " expected one for every " << nLayer << " layers " << std::endl ;
170  throw Exception( s.str() ) ;
171 
172  }
173 
174  _vxdCount.resize( nLayer ) ;
175 }
176 
177 void VTXDigiProcessor::processRunHeader( LCRunHeader* /*run*/) {
178  _nRun++ ;
179 }
180 
181 void VTXDigiProcessor::processEvent( LCEvent * evt ) {
182 
183  gsl_rng_set( _rng, Global::EVENTSEEDER->getSeed(this) ) ;
184  streamlog_out( DEBUG ) << "seed set to " << Global::EVENTSEEDER->getSeed(this) << std::endl;
185 
186  for (int iColl=0;iColl<3;++iColl) {
187 
188  LCCollection* STHcol = 0 ;
189  try{
190  if (iColl==0)
191  STHcol = evt->getCollection( _colNameVTX ) ;
192  else if (iColl==1)
193  STHcol = evt->getCollection( _colNameSIT ) ;
194  else
195  STHcol = evt->getCollection( _colNameSET ) ;
196  }
197  catch(DataNotAvailableException &e){
198 
199  if (iColl==0)
200  streamlog_out(DEBUG) << "Collection " << _colNameVTX.c_str() << " is unavailable in event " << _nEvt << std::endl;
201  else if (iColl==1)
202  streamlog_out(DEBUG) << "Collection " << _colNameSIT.c_str() << " is unavailable in event " << _nEvt << std::endl;
203  else
204  streamlog_out(DEBUG) << "Collection " << _colNameSET.c_str() << " is unavailable in event " << _nEvt << std::endl;
205  }
206 
207  if( STHcol != 0 ){
208 
209  LCCollectionVec* trkhitVec = new LCCollectionVec( LCIO::TRACKERHIT ) ;
210 
211  int nSimHits = STHcol->getNumberOfElements() ;
212 
213  for(int i=0; i< nSimHits; i++){
214 
215  SimTrackerHit* SimTHit = dynamic_cast<SimTrackerHit*>( STHcol->getElementAt( i ) ) ;
216 
217  //fg: --- accept only activeSETLayers :
218  if( iColl==2 ) { // SET
219 
220  // fg: the layer number is the cellID (for Mokka at least)
221  int cellID = SimTHit->getCellID0() ;
222 
223  if( find(_activeSETLayers.begin(),_activeSETLayers.end(),cellID)==_activeSETLayers.end() ) {
224  continue ; // ----------------- ignore hit
225  }
226  }
227 
228  if (_removeDRays) { // check if hit originates from delta-electron
229  float totMomentum = 0;
230  for (int i=0;i<3;++i)
231  {
232  totMomentum+=SimTHit->getMomentum()[i]*SimTHit->getMomentum()[i];
233  }
234  totMomentum = sqrt(totMomentum);
235 
236  if (totMomentum < _momCut)
237  {
238  streamlog_out( DEBUG ) << " removeDRays enabled: hit originates from delta-electron, hit dropped" << std::endl ;
239  continue ; // ----------------- ignore hit
240  }
241  }
242 
243 
244  const int celId = SimTHit->getCellID0() ;
245 
246  const double *pos ;
247  pos = SimTHit->getPosition() ;
248 
249  double smearedPos[3];
250 
251  //VXD smearing
252  if (iColl==0) {
253 
254  streamlog_out( DEBUG ) << " processing collection " << _colNameVTX
255  << " with " << nSimHits << " hits ... " << std::endl ;
256 
257  //find which layer hit is in - encoded in cell ID
258  int layer = SimTHit->getCellID0() - 1;
259 
260 
261  _vxdCount[layer].second++ ;
262  // drop hit due to inefficiency ?
263  double urand = gsl_rng_uniform( _rng ) ;
264 
265  if( urand > _vxdEff[ layer ] ){
266  streamlog_out( DEBUG ) << " dropping hit in layer " << layer << std::endl ;
267  continue ; // ----------------- ignore hit
268  }
269  _vxdCount[layer].first++ ;
270 
271 
272  //get VXD geometry info
273  const gear::VXDParameters& gearVXD = Global::GEAR->getVXDParameters() ;
274  const gear::VXDLayerLayout& layerVXD = gearVXD.getVXDLayerLayout();
275 
276  gear::Vector3D hitvec(pos[0],pos[1],pos[2]);
277  gear::Vector3D smearedhitvec(pos[0],pos[1],pos[2]);
278 
279  streamlog_out(DEBUG) <<"Position of hit before smearing = "<<pos[0]<<" "<<pos[1]<<" "<<pos[2]<<endl;
280 
281  //check detector geometry to decide how to smear hits
282  //ladders in layer -> need to smear hits along ladder plane
283 
284  if( _smearAlongLadders !=0 && layerVXD.getNLadders(0) !=0 ) {
285 
286  streamlog_out(DEBUG) << "start smearing along ladders for: " << layer << std::endl;
287 
288  int layer = SimTHit->getCellID0() - 1;
289 
290  //phi between each ladder
291  double deltaPhi = ( 2 * M_PI ) / layerVXD.getNLadders(layer) ;
292 
293  double PhiInLocal(0.0);
294  //find the ladder that the hit is in
295  int ladderIndex = -1;
296  double ladderPhi=999;
297 
298  for (int ic=0; ic < layerVXD.getNLadders(layer); ++ic) {
299 
300  ladderPhi = correctPhiRange( layerVXD.getPhi0( layer ) + ic*deltaPhi ) ;
301 
302  PhiInLocal = hitvec.phi() - ladderPhi;
303  double RXY = hitvec.rho();
304 
305  // check if point is in range of ladder
306  if (RXY*cos(PhiInLocal) - layerVXD.getSensitiveDistance(layer) > -layerVXD.getSensitiveThickness(layer) &&
307  RXY*cos(PhiInLocal) - layerVXD.getSensitiveDistance(layer) < layerVXD.getSensitiveThickness(layer) )
308  {
309  ladderIndex = ic;
310  break;
311  }
312  }
313 
314  double sensitive_width = layerVXD.getSensitiveWidth(layer);
315  double sensitive_offset = layerVXD.getSensitiveOffset(layer);
316 
317  double ladder_incline = correctPhiRange( (M_PI/2.0 ) + ladderPhi );
318 
319  double u = (hitvec.rho() * sin(PhiInLocal) - sensitive_offset );
320 
321  streamlog_out(DEBUG) << ":"
322  << " Event: " << _nEvt
323  << " hit: " << i
324  << " of " << nSimHits
325  << " layer: " << layer
326  << " ladderIndex: " << ladderIndex
327  << " half ladder width " << sensitive_width * 0.5
328  << " u: " << u
329  << " layer sensitive_offset " << sensitive_offset
330  << " layer phi0 " << layerVXD.getPhi0( layer )
331  << " phi: " << hitvec.phi()
332  << " PhiInLocal: " << PhiInLocal
333  << " ladderPhi: " << ladderPhi
334  << " ladder_incline: " << ladder_incline
335  << std::endl;
336 
337  if( u > sensitive_width * 0.5 || u < -sensitive_width * 0.5)
338  {
339  streamlog_out(DEBUG) << "hit not in sensitive: u: " << u << " half ladder width = " << sensitive_width * 0.5 << std::endl;
340  continue; // hit is not in sensitive so drop this hit and go on to the next
341  }
342 
343  int tries = 0;
344  // try to smear the hit within the ladder
345  bool accept_hit = false;
346  while( tries < 100 )
347  {
348 
349  if(tries > 0) streamlog_out(DEBUG) << "retry smearing for " << layer << " " << ladderIndex << " : retries " << tries << std::endl;
350 
353 
354  double rPhiSmear = gsl_ran_gaussian(_rng, _pointResoRPhi);
355 
356  if( (u+rPhiSmear) < sensitive_width * 0.5 && (u+rPhiSmear) > -sensitive_width * 0.5)
357  {
358  accept_hit =true;
359  double zSmear = gsl_ran_gaussian(_rng, _pointResoZ);
360 
361  //find smearing for x and y, so that hit is smeared along ladder plane
362  smearedPos[0] = hitvec.x() + rPhiSmear * cos(ladder_incline);
363  smearedPos[1] = hitvec.y() + rPhiSmear * sin(ladder_incline);
364  smearedPos[2] = hitvec.z() + zSmear;
365  break;
366 
367  }
368  ++tries;
369  }
370  if( accept_hit == false )
371  {
372  streamlog_out(DEBUG) << "hit could not be smeared within ladder after 100 tries: hit dropped" << std::endl;
373  continue;
374  } //
375  }
376 
377  else // no ladders in layers -> just smear around cylinders
378  {
379 
380  streamlog_out(DEBUG) << "start simple smearing for: " << layer << std::endl;
381  CLHEP::Hep3Vector point(pos[0], pos[1], pos[2]);
382 
385 
386  double rphiSmear = gsl_ran_gaussian(_rng, _pointResoRPhi);
387  double zSmear = gsl_ran_gaussian(_rng, _pointResoZ);
388 
389  point.setPhi( point.phi() + rphiSmear / point.perp() );
390  point.setZ( point.z() + zSmear );
391 
392  smearedPos[0] = point.x();
393  smearedPos[1] = point.y();
394  smearedPos[2] = point.z();
395  }
396 
397  }
398  // SIT/SET Smearing
399  else {
400 
401  if (iColl==1) {
404  }
405  else {
408  }
409 
410  double xSmear = gsl_ran_gaussian(_rng, _pointResoRPhi);
411  double zSmear = gsl_ran_gaussian(_rng, _pointResoZ);
412 
413  double phi = atan2(pos[1],pos[0]);
414  double rad = sqrt(pos[1]*pos[1]+pos[0]*pos[0]);
415  double phi_new = phi + xSmear/rad;
416  smearedPos[0] = rad*cos(phi_new);
417  smearedPos[1] = rad*sin(phi_new);
418  smearedPos[2] = pos[2] + zSmear;
419 
420  }
421 
422  float edep ;
423  float dedxSmear = 0.0 ;
424  edep = SimTHit->getEDep() ;
425 
426  edep = edep + dedxSmear ;
427 
428  MCParticle *mcp ;
429  mcp = SimTHit->getMCParticle() ;
430 
431  //store hit variables
432  TrackerHitImpl* trkHit = new TrackerHitImpl ;
433 
434  //FIXME: SJA: this is a temporary work around the set'er should take a const double *
435  trkHit->setPosition( smearedPos ) ;
436 
437  trkHit->setEDep( edep ) ;
438  if (iColl==0)
439  trkHit->setType(100+celId );
440  else {
441  trkHit->setType(400+celId);
442  }
443 
444  float covMat[TRKHITNCOVMATRIX]={0.,0.,_pointResoRPhi*_pointResoRPhi,0.,0.,_pointResoZ*_pointResoZ};
445  trkHit->setCovMatrix(covMat);
446  // push back the SimTHit for this TrackerHit
447  // fg: only if we have a sim hit with proper link to MC truth
448  if( mcp != 0 ) {
449  trkHit->rawHits().push_back( SimTHit ) ;
450  }
451  //else{
452  // streamlog_out( DEBUG ) << " ignore simhit pointer as MCParticle pointer is NULL ! " << std::endl ;
453  //}
454 
455 
456  trkhitVec->addElement( trkHit ) ;
457  }
458 
459 
460  if (iColl==0)
461  evt->addCollection( trkhitVec , _outColNameVTX ) ;
462  else if (iColl == 1)
463  evt->addCollection( trkhitVec , _outColNameSIT ) ;
464  else
465  evt->addCollection( trkhitVec , _outColNameSET );
466  }
467  }
468  _nEvt ++ ;
469 }
470 
471 
472 
473 void VTXDigiProcessor::check( LCEvent * /*evt*/ ) {
474  // nothing to check here - could be used to fill checkplots in reconstruction processor
475 }
476 
477 
479 
480  streamlog_out(MESSAGE) << " end() " << name()
481  << " processed " << _nEvt << " events in " << _nRun << " runs "
482  << std::endl ;
483 
484  streamlog_out(DEBUG) << " VXD hits - efficiency : " << std::endl ;
485  for(unsigned i=0 ; i<_vxdCount.size(); ++i) {
486 
487  streamlog_out(DEBUG) << " layer " << i << " kept "
488  << _vxdCount[i].first << " hits of "
489  << _vxdCount[i].second << " -> eff = "
490  << double(_vxdCount[i].first)/ double(_vxdCount[i].second)
491  << std::endl ;
492 
493  }
494 }
495 
496 
497 double VTXDigiProcessor::correctPhiRange( double Phi ) const {
498 
499  while( (Phi < -1.0*M_PI) || (Phi > 1.0*M_PI) )
500  {
501  if( Phi > 1.0*M_PI )
502  {
503  Phi -= 2.0 * M_PI;
504  }
505  else
506  {
507  Phi += 2.0 * M_PI;
508  }
509  }
510 
511  return Phi ;
512 
513 } // function correctPhiRange
514 
virtual void end()
Called after data processing for clean up.
virtual void check(LCEvent *evt)
CLHEP::Hep3Vector Vector3D
std::string _outColNameVTX
std::vector< std::pair< long, long > > _vxdCount
std::string _outColNameSET
std::string _outColNameSIT
VTXDigiProcessor aVTXDigiProcessor
static const float s
std::string _colNameVTX
double correctPhiRange(double Phi) const
std::string _colNameSET
static const float e
std::vector< int > _activeSETLayers
virtual void processRunHeader(LCRunHeader *run)
Called for every run.
std::vector< LCCollection * > LCCollectionVec
Definition: SiStripClus.h:55
virtual void processEvent(LCEvent *evt)
Called for every event - the working horse.
virtual void init()
Called at the begin of the job before anything is read.
std::string _colNameSIT