All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups
SiTracker_dEdxProcessor.cc
Go to the documentation of this file.
2 
3 #include <EVENT/LCCollection.h>
4 #include <EVENT/MCParticle.h>
5 #include <IMPL/TrackImpl.h>
6 //#include <EVENT/Track.h>
7 #include <EVENT/LCRelation.h>
8 #include <UTIL/LCRelationNavigator.h>
9 #include <IMPL/TrackStateImpl.h>
10 #include <IMPL/TrackerHitImpl.h>
11 
12 // ----- include for verbosity dependent logging ---------
13 #include "marlin/VerbosityLevels.h"
14 
15 #include <DD4hep/Detector.h>
16 #include "DD4hep/DD4hepUnits.h"
17 #include "DDRec/DDGear.h"
18 #include "DDRec/DetectorData.h"
19 #include <DD4hep/DetType.h>
20 #include <DDRec/Vector3D.h>
21 
22 #include "marlin/Global.h"
23 #include <MarlinTrk/IMarlinTrack.h>
24 #include <MarlinTrk/IMarlinTrkSystem.h>
25 #include "MarlinTrk/MarlinTrkUtils.h"
26 
27 #include <TVector3.h>
28 #include <TROOT.h>
29 
30 #include <climits>
31 
32 
33 dEdxPoint::dEdxPoint(const double _dE, const double _dx) :
34  dE(_dE), dx(_dx), dEdx(_dE/_dx) {}
35 
37  dE(orig.Get_dE()), dx(orig.Get_dx()), dEdx(orig.Get_dE()/orig.Get_dx()) {}
38 
40 
41 
42 SiTracker_dEdxProcessor::SiTracker_dEdxProcessor() : Processor("SiTracker_dEdxProcessor"),
43  m_trackCollName(""), m_trkHitCollNames(),
44  surfMap(NULL), trkSystem(NULL), _bField(0),
45  layerFinder(NULL),
46  lastRunHeaderProcessed(-1),
47  timers(),
48  lastTP(std::chrono::high_resolution_clock::now()),
49  newTP(std::chrono::high_resolution_clock::now())
50  {
51 
52  // modify processor description
53  _description = "SiTracker_dEdxProcessor calculates dE/dx for planar silicon trackers" ;
54 
55 
56  // register steering parameters: name, description, class-variable, default value
57 
58  registerInputCollection( LCIO::TRACK,
59  "TrackCollectionName" ,
60  "Name of the input Track collection" ,
62  std::string("SiTracks")
63  );
64 
65 
66  StringVec defaultTrkHitCollections;
67  defaultTrkHitCollections.push_back(std::string("ITrackerHits"));
68  defaultTrkHitCollections.push_back(std::string("ITrackerEndcapHits"));
69  defaultTrkHitCollections.push_back(std::string("OTrackerHits"));
70  defaultTrkHitCollections.push_back(std::string("OTrackerEndcapHits"));
71  defaultTrkHitCollections.push_back(std::string("VXDTrackerHits"));
72  defaultTrkHitCollections.push_back(std::string("VXDEndcapTrackerHits"));
73 
74  registerProcessorParameter("TrkHitCollections" ,
75  "Tracker hit collections that will be analysed",
77  defaultTrkHitCollections ) ;
78 
79  int elementMask = 0;
80  for (unsigned ibit=0; ibit<sizeof(int)*CHAR_BIT; ibit++) {
81  elementMask += 1 << ibit;
82  }
83 
84  registerProcessorParameter("CheatSensorThicknesses" ,
85  "Shall we use the sensitive thicknesses from parameters?",
87  false ) ;
88 
89  FloatVec sensThicknessCheatVals;
90  for (unsigned i=0; i<defaultTrkHitCollections.size(); i++) {
91  sensThicknessCheatVals.push_back(-1);
92  }
93 
94  registerProcessorParameter("SensorThicknessCheatValues" ,
95  "Sensor thicknesses to use instead of automatic values from DD4hep (if CheatSensorThicknesses==true).",
97  sensThicknessCheatVals ) ;
98 
99  /* Type of estimator for dEdx
100  * Available estimators: mean, median, truncMean, harmonic, harmonic-2, weighted-harmonic, weighted-harmonic-2
101  */
102  registerProcessorParameter("dEdxEstimator" ,
103  "Type of estimator for dEdx.",
105  std::string("median") ) ;
106 
107 }
108 
109 
111 
112  if (layerFinder) delete layerFinder;
113 }
114 
115 
117 
118  streamlog_out(DEBUG) << " init called " << std::endl ;
119 
120  // usually a good idea to
121  printParameters() ;
122 
123  if(m_dEdxEstimator.compare("mean") == 0) {
125  }
126  else if(m_dEdxEstimator.compare("median") == 0) {
128  }
129  else if (m_dEdxEstimator.compare("truncMean") == 0) {
131  }
132  else if (m_dEdxEstimator.compare("harmonic") == 0) {
134  }
135  else if (m_dEdxEstimator.compare("harmonic-2") == 0) {
137  }
138  else if (m_dEdxEstimator.compare("weighted-harmonic") == 0) {
140  }
141  else if (m_dEdxEstimator.compare("weighted-harmonic-2") == 0) {
143  }
144  else {
145  streamlog_out(ERROR) << "Unknown dE/dx evaluation method " << m_dEdxEstimator << ". Exiting.\n";
146  exit(0);
147  }
148 
149  dd4hep::Detector& theDetector = dd4hep::Detector::getInstance();
150 
151  dd4hep::rec::SurfaceManager& surfMan = *theDetector.extension< dd4hep::rec::SurfaceManager >() ;
152  surfMap = surfMan.map( "tracker" ) ;
153 
155  m_sensThicknessCheatVals.clear();
156  for(unsigned isub=0; isub<m_trkHitCollNames.size(); isub++) {
157  // This is how we tell the collection finder that we do not want to cheat any thickness values
158  m_sensThicknessCheatVals.push_back(-1.);
159  }
160  }
161 
163  // exit(0);
164 
165  const double pos[3]={0,0,0};
166  double bFieldVec[3]={0,0,0};
167  theDetector.field().magneticField(pos,bFieldVec); // get the magnetic field vector from DD4hep
168  _bField = bFieldVec[2]/dd4hep::tesla; // z component at (0,0,0)
169 
170  //trksystem for marlin track
171 
172  trkSystem = MarlinTrk::Factory::createMarlinTrkSystem( "DDKalTest" , marlin::Global::GEAR , "" ) ;
173 
174  if( trkSystem == 0 ) throw EVENT::Exception( std::string(" Cannot initialize MarlinTrkSystem of Type: ") + std::string("DDKalTest") );
175 
176  trkSystem->setOption( MarlinTrk::IMarlinTrkSystem::CFG::useQMS, true );
177  //_MSOn ) ;
178  trkSystem->setOption( MarlinTrk::IMarlinTrkSystem::CFG::usedEdx, false) ;
179  trkSystem->setOption( MarlinTrk::IMarlinTrkSystem::CFG::useSmoothing, true) ;
180  trkSystem->init() ;
181 
182 
183  gROOT->ProcessLine("#include <vector>");
184 
186 
187  for (unsigned i=0; i<nTimers; i++) {
188  timers.push_back(std::chrono::duration<double>(std::chrono::duration_values<double>::zero()));
189  }
190 
191  streamlog_out(DEBUG) << " init done " << std::endl ;
192 
193 }
194 
195 
197 
198  lastRunHeaderProcessed = run->getRunNumber();
199 
200 }
201 
202 
203 
205 
206 /* if (_lastRunHeaderProcessed < evt->getRunNumber()) {
207 // streamlog_out(ERROR) << "Run header has not been processed for this run! Exiting.\n";
208 // exit(0);
209  }*/
210 
211  if(evt->getEventNumber()%100 == 0) {
212  streamlog_out(MESSAGE) << " processing event: " << evt->getEventNumber()
213  << " in run: " << evt->getRunNumber() << std::endl ;
214  }
215 
216 
217  /************************************/
218  /*** Get collections ***/
219  /************************************/
220 
221  lastTP = std::chrono::high_resolution_clock::now();
222 
223  LCCollection* tracks = NULL;
224  try {
225  tracks = evt->getCollection(m_trackCollName);
226  }
227  catch(EVENT::DataNotAvailableException &dataex) {
228  streamlog_out(MESSAGE) << "Collection " << m_trackCollName << " not found. Skipping event #" << evt->getEventNumber() << ".\n";
229  tracks = NULL;
230  return;
231  }
232 
233  tracks->getFlag();
234 
235 
236  addTime(0);
237 
238 
239  /*** Read collections to find a valid decoder for CELLID encoding ***/
240  if (layerFinder->ReadCollections(evt) != 0) {
241  streamlog_out(WARNING) << "None of the requested collections found in event #" << evt->getEventNumber() << ". Skipping event.\n";
242  return;
243  }
244 
245  //layerFinder->ReportHandledDetectors();
246 
247  addTime(1);
248 
249  int nTracks = tracks->getNumberOfElements() ;
250 
251  for (int i = 0; i < nTracks; i++)
252  {
253  streamlog_out(DEBUG5) << "Processing track #" << i << ".\n";
254  TrackImpl * track = dynamic_cast<TrackImpl*>( tracks->getElementAt(i) );
255 
256  /*** Analyse hits and get dE/dx from each ***/
257 
258  EVENT::TrackerHitVec trackhits = track->getTrackerHits();
259 
260  MarlinTrk::IMarlinTrack* marlin_trk = trkSystem->createTrack();
261  for( auto it : trackhits ){
262  marlin_trk->addHit(it);
263  }//end loop on hits
264 
265  const TrackStateImpl *trackState = dynamic_cast<const TrackStateImpl*>(track->getTrackState(TrackState::AtFirstHit));
266  if (!trackState) {
267  streamlog_out(WARNING) << "Cannot get track state for track #" << i
268  << " in event " << evt->getEventNumber() << std::endl;
269  streamlog_out(WARNING) << "Skipping track.\n";
270  continue;
271  }
272 
273  marlin_trk->initialise( *trackState, _bField, MarlinTrk::IMarlinTrack::forward ) ;
274 
275  addTime(2);
276 
277  dEdxVec dEdxHitVec;
278 
279  for(unsigned int ihit = 0; ihit < trackhits.size(); ihit++) {
280 
281  // Tangent to the track at hit position
282  dd4hep::rec::Vector3D hitpos(trackhits[ihit]->getPosition());
283 
284  IMPL::TrackStateImpl ts;
285  double chi2 = 0.;
286  int ndf = 0;
287  marlin_trk->extrapolate(hitpos, ts, chi2, ndf);
288 
289  addTime(3);
290 
291  dd4hep::rec::Vector3D rp(ts.getReferencePoint());
292 
293  float tanLambda = ts.getTanLambda();
294  float sinTheta = 1. / sqrt(1.+pow(tanLambda,2));
295  float phi = ts.getPhi();
296  float trackDirX = cos(phi)*sinTheta;
297  float trackDirY = sin(phi)*sinTheta;
298  float trackDirZ = tanLambda*sinTheta;
299  dd4hep::rec::Vector3D trackDir(trackDirX, trackDirY, trackDirZ);
300 
301  addTime(4);
302 
303  // Normal to the surface of hit
304  unsigned long cellid = trackhits[ihit]->getCellID0();
305  dd4hep::rec::SurfaceMap::const_iterator surface = surfMap->find(cellid);
306  if (surface == surfMap->end()) {
307  streamlog_out(ERROR) << "Cannot find the surface corresponding to track hit ID " << cellid
308  << " in event " << evt->getEventNumber() << "!\n";
309  exit(0);
310  }
311  dd4hep::rec::Vector3D surfaceNormal = surface->second->normal();
312 
313  addTime(5);
314 
315  double norm = sqrt(trackDir.dot(trackDir)*surfaceNormal.dot(surfaceNormal));
316  if (norm < FLT_MIN) continue;
317  double cosAngle = fabs(trackDir.dot(surfaceNormal)) / norm ;
318 
319  double thickness = layerFinder->SensitiveThickness(dynamic_cast<TrackerHitPlane*>(trackhits[ihit]));
320  if (thickness < 0.) {
321  streamlog_out(ERROR) << "Could not find hit collection corresponding to hit CellID " << cellid
322  << ", hit ID " << trackhits.at(ihit)->id() << " .\n";
323  streamlog_out(ERROR) << "Event #" << evt->getEventNumber() << ".\n";
324  exit(0);
325  }
326  if (thickness < 0.00001) {
327  streamlog_out(ERROR) << "GetThickness returned zero!\n";
328  exit(0);
329  }
330 
331  double effThickness = thickness / cosAngle;
332 
333  dEdxHitVec.push_back( dEdxPoint(trackhits[ihit]->getEDep(), effThickness) );
334 
335  addTime(6);
336 
337  }
338 
339 
340  if(dEdxHitVec.size() == 0) continue;
341 
342  double dEdx, dEdxError;
343  dEdx = dEdxEval(dEdxHitVec, dEdxError);
344  // Todo: This is read-only if track is read from existing lcio file!
345  // Is there a way to process tracks that are read from the input file?
346  track->setdEdx(dEdx);
347  track->setdEdxError(dEdxError);
348 
349  addTime(7);
350  }
351 
352 }
353 
354 
355 
356 
357 
358 void SiTracker_dEdxProcessor::check( LCEvent * /*evt*/ ) {
359  // nothing to check here - could be used to fill checkplots in reconstruction processor
360 }
361 /**/
362 
364 
365  for (unsigned i=0; i<timers.size(); i++) {
366  streamlog_out(MESSAGE) << "Total time in timer #" << i << ": " << timers.at(i).count() << " s\n";
367  }
368  // std::cout << "SiTracker_dEdxProcessor::end() " << name()
369  // << " processed " << _nEvt << " events in " << _nRun << " runs "
370  // << std::endl ;
371 
372  delete layerFinder;
373  layerFinder = NULL;
374 }
375 
376 
377 
378 /*************************************************************
379  *
380  * Evaluation methods for dE/dx
381  *
382  ************************************************************/
383 
386 
387 // Weighted truncated mean with arbitrary truncation
388 // Weight of a measurement is the material thickness traversed in the hit
390  const double truncLo, const double truncHi) {
391 
392  const unsigned n = hitVec.size();
393  const unsigned iStart = static_cast<unsigned>(floor(n*truncLo + 0.5));
394  const unsigned iEnd = static_cast<unsigned>(floor(n*(1-truncHi) + 0.5));
395 
396  if(iEnd-iStart == 0) {
397  dEdxError = 0;
398  return 0;
399  }
400  if(iEnd-iStart == 1) {
401  dEdxError = hitVec.at(iStart).Get_dEdx() ;
402  return hitVec.at(iStart).Get_dEdx() ;
403  }
404 
405  sort(hitVec.begin(), hitVec.end(), dEdxOrder);
406 
407  double eDepSum = 0.;
408  double thickness = 0.;
409  double mu2dEdx = 0.;
410  for (unsigned i=iStart; i<iEnd; i++) {
411  eDepSum += hitVec.at(i).Get_dE();
412  thickness += hitVec.at(i).Get_dx();
413  mu2dEdx += pow(hitVec.at(i).Get_dE(), 2) / hitVec.at(i).Get_dx();
414  }
415 
416  mu2dEdx /= thickness;
417 
418  double track_dEdx = eDepSum / thickness;
419  dEdxError = sqrt((mu2dEdx - pow(track_dEdx, 2))/(iEnd-iStart));
420  return track_dEdx;
421 }
422 
423 
424 // Weighted mean
425 // Weight of a measurement is the material thickness traversed in the hit
426 double SiTracker_dEdxProcessor::dEdxMean(dEdxVec hitVec, double &dEdxError) {
427 
428  return dEdxGeneralTruncMean(hitVec, dEdxError, 0., 0.);
429 }
430 
431 
432 // Median
433 double SiTracker_dEdxProcessor::dEdxMedian(dEdxVec hitVec, double &dEdxError) {
434 
435  const unsigned n = hitVec.size();
436  if(n == 0) {
437  dEdxError = 0;
438  return 0;
439  }
440  if(n == 1) {
441  dEdxError = hitVec.at(0).Get_dEdx();
442  return hitVec.at(0).Get_dEdx();
443  }
444 
445  sort(hitVec.begin(), hitVec.end(), dEdxOrder);
446  double median=0.;
447  if (n%2 ==1) {
448  median = hitVec.at(n/2).Get_dEdx();
449  }
450  else {
451  median = (hitVec.at(n/2-1).Get_dEdx() + hitVec.at(n/2).Get_dEdx()) / 2;
452  }
453 
454  // Substituting error of the mean for dEdxError here
455  // instead of bootstrapping the error of the median
456  dEdxMean(hitVec, dEdxError);
457  return median;
458 }
459 
460 
461 // Weighted truncated mean with standard truncation
462 // Weight of a measurement is the material thickness traversed in the hit
463 double SiTracker_dEdxProcessor::dEdxTruncMean(dEdxVec hitVec, double &dEdxError) {
464 
465  return dEdxGeneralTruncMean(hitVec, dEdxError, truncFractionLo, truncFractionUp);
466 }
467 
468 
469 // Simple harmonic mean
470 double SiTracker_dEdxProcessor::dEdxHarmonic(dEdxVec hitVec, double &dEdxError) {
471 
472  const unsigned n = hitVec.size();
473  if(n == 0) {
474  dEdxError = 0;
475  return 0;
476  }
477  if(n == 1) {
478  dEdxError = hitVec.at(0).Get_dEdx();
479  return hitVec.at(0).Get_dEdx();
480  }
481 
482  // Calculation of the first and the second moment of
483  // 1 / (dE/dx)
484  double mu1sum = 0.;
485  double mu2sum = 0.;
486  for (unsigned i=0; i<n; i++) {
487  double inverse = 1/hitVec.at(i).Get_dEdx();
488  mu1sum += inverse;
489  mu2sum += pow( inverse, 2 );
490  }
491 
492  double mu2 = mu2sum / n;
493  double mu1 = mu1sum / n;
494  double sigma = sqrt( (mu2 - pow(mu1, 2)) / n );
495 
496  double dEdx = 1 / mu1;
497  dEdxError = sigma / pow(mu1, 2) ;
498 
499  return dEdx;
500 }
501 
502 
503 // Simple harmonic-squared mean
504 double SiTracker_dEdxProcessor::dEdxHarmonic2(dEdxVec hitVec, double &dEdxError) {
505 
506  const unsigned n = hitVec.size();
507  if(n == 0) {
508  dEdxError = 0;
509  return 0;
510  }
511  if(n == 1) {
512  dEdxError = hitVec.at(0).Get_dEdx();
513  return hitVec.at(0).Get_dEdx();
514  }
515 
516  // Calculation of the first and the second moment of
517  // 1 / (dE/dx)^2
518  double mu1sum = 0.;
519  double mu2sum = 0.;
520  for (unsigned i=0; i<n; i++) {
521  double sqinverse = pow(hitVec.at(i).Get_dEdx(), -2);
522  mu1sum += sqinverse;
523  mu2sum += pow( sqinverse, 2 );
524  }
525 
526  double mu2 = mu2sum / n;
527  double mu1 = mu1sum / n;
528  double sigma = sqrt( (mu2 - pow(mu1, 2)) / n );
529 
530  double dEdx = 1 / sqrt(mu1);
531  dEdxError = sigma * pow(dEdx, 3) / 2 ;
532 
533  return dEdx;
534 }
535 
536 
537 // Weighted harmonic mean
538 // Weight of a measurement is the material thickness traversed in the hit
539 double SiTracker_dEdxProcessor::dEdxWgtHarmonic(dEdxVec hitVec, double &dEdxError) {
540 
541  const unsigned n = hitVec.size();
542  if(n == 0) {
543  dEdxError = 0;
544  return 0;
545  }
546  if(n == 1) {
547  dEdxError = hitVec.at(0).Get_dEdx();
548  return hitVec.at(0).Get_dEdx();
549  }
550 
551  // Calculation of the first and the second moment of
552  // 1 / (dE/dx)
553  double mu1sum = 0.;
554  double mu2sum = 0.;
555  double wgtsum = 0.;
556  for (unsigned i=0; i<n; i++) {
557  double inverse = 1/hitVec.at(i).Get_dEdx();
558  double wgt = hitVec.at(i).Get_dx();
559  mu1sum += wgt*inverse;
560  mu2sum += wgt*pow( inverse, 2 );
561  wgtsum += wgt;
562  }
563 
564  double mu2 = mu2sum / wgtsum;
565  double mu1 = mu1sum / wgtsum;
566  double sigma = sqrt( (mu2 - pow(mu1, 2)) / n );
567 
568  double dEdx = 1 / mu1;
569  dEdxError = sigma * pow(dEdx, 2) ;
570 
571  return dEdx;
572 }
573 
574 
575 // Weighted harmonic-squared mean
576 // Weight of a measurement is the material thickness traversed in the hit
577 double SiTracker_dEdxProcessor::dEdxWgtHarmonic2(dEdxVec hitVec, double &dEdxError) {
578 
579  const unsigned n = hitVec.size();
580  if(n == 0) {
581  dEdxError = 0;
582  return 0;
583  }
584  if(n == 1) {
585  dEdxError = hitVec.at(0).Get_dEdx();
586  return hitVec.at(0).Get_dEdx();
587  }
588 
589  // Calculation of the first and the second moment of
590  // 1 / (dE/dx)^2
591  double mu1sum = 0.;
592  double mu2sum = 0.;
593  double wgtsum = 0.;
594  for (unsigned i=0; i<n; i++) {
595  double sqinverse = pow(hitVec.at(i).Get_dEdx(), -2);
596  double wgt = hitVec.at(i).Get_dx();
597  mu1sum += wgt*sqinverse;
598  mu2sum += wgt*pow( sqinverse, 2 );
599  wgtsum += wgt;
600  }
601 
602  double mu2 = mu2sum / wgtsum;
603  double mu1 = mu1sum / wgtsum;
604  double sigma = sqrt( (mu2 - pow(mu1, 2)) / n );
605 
606  double dEdx = 1 / sqrt(mu1);
607  dEdxError = sigma * pow(dEdx, 3) / 2 ;
608 
609  return dEdx;
610 }
611 
const dd4hep::rec::SurfaceMap * surfMap
static double dEdxHarmonic2(dEdxVec, double &dEdxError)
CLHEP::Hep3Vector Vector3D
static double dEdxHarmonic(dEdxVec, double &dEdxError)
virtual void end()
Called after data processing for clean up.
virtual void check(LCEvent *evt)
static double dEdxTruncMean(dEdxVec, double &dEdxError)
std::vector< std::chrono::duration< double > > timers
SiTracker_dEdxProcessor aSiTracker_dEdxProcessor
virtual void processRunHeader(LCRunHeader *run)
Called at the end of every run.
static double dEdxGeneralTruncMean(dEdxVec, double &dEdxError, const double truncLo=0, const double truncHi=0)
int ReadCollections(EVENT::LCEvent *)
Definition: LayerFinder.cc:201
virtual void processEvent(LCEvent *evt)
Called for every event - the working horse.
static double dEdxWgtHarmonic2(dEdxVec, double &dEdxError)
static double dEdxWgtHarmonic(dEdxVec, double &dEdxError)
MarlinTrk::IMarlinTrkSystem * trkSystem
SiTracker_dEdxProcessor for Marlin.
static double dEdxMean(dEdxVec, double &dEdxError)
std::vector< dEdxPoint > dEdxVec
std::chrono::high_resolution_clock::time_point lastTP
double SensitiveThickness(lcio::TrackerHitPlane *)
Definition: LayerFinder.cc:213
static bool dEdxOrder(dEdxPoint p1, dEdxPoint p2)
static double dEdxMedian(dEdxVec, double &dEdxError)
dEdxPoint(const double _dE, const double _dx)
std::vector< std::string > StringVec
Definition: SiStripClus.h:56
virtual void init()
Called at the begin of the job before anything is read.