Belle II Software  release-08-01-10
CDCDedxPIDModule.cc
1 /**************************************************************************
2  * basf2 (Belle II Analysis Software Framework) *
3  * Author: The Belle II Collaboration *
4  * *
5  * See git log for contributors and copyright holders. *
6  * This file is licensed under LGPL-3.0, see LICENSE.md. *
7  **************************************************************************/
8 
9 #include <reconstruction/modules/CDCDedxPID/CDCDedxPIDModule.h>
10 
11 #include <reconstruction/dataobjects/DedxConstants.h>
12 #include <reconstruction/modules/CDCDedxPID/LineHelper.h>
13 
14 #include <framework/gearbox/Const.h>
15 
16 #include <cdc/dataobjects/CDCHit.h>
17 #include <cdc/dataobjects/CDCRecoHit.h>
18 
19 #include <cdc/translators/LinearGlobalADCCountTranslator.h>
20 #include <cdc/translators/RealisticTDCCountTranslator.h>
21 
22 #include <cdc/geometry/CDCGeometryPar.h>
23 #include <tracking/dataobjects/RecoHitInformation.h>
24 
25 #include <genfit/AbsTrackRep.h>
26 #include <genfit/Exception.h>
27 #include <genfit/MaterialEffects.h>
28 #include <genfit/KalmanFitterInfo.h>
29 
30 #include <TH2F.h>
31 #include <TRandom.h>
32 
33 #include <memory>
34 #include <cmath>
35 #include <algorithm>
36 
37 using namespace Belle2;
38 using namespace CDC;
39 using namespace Dedx;
40 
41 REG_MODULE(CDCDedxPID);
42 
44 {
46 
47  //Set module properties
48  setDescription("Extract dE/dx and corresponding log-likelihood from fitted tracks and hits in the CDC.");
49 
50  //Parameter definitions
51  addParam("usePrediction", m_usePrediction,
52  "Use parameterized means and resolutions to determine PID values. If false, lookup table PDFs are used.", true);
53  addParam("removeLowest", m_removeLowest,
54  "Portion of events with low dE/dx that should be discarded", double(0.05));
55  addParam("removeHighest", m_removeHighest,
56  "Portion of events with high dE/dx that should be discarded", double(0.25));
57  addParam("useBackHalfCurlers", m_backHalfCurlers,
58  "Whether to use the back half of curlers", false);
59  addParam("enableDebugOutput", m_enableDebugOutput,
60  "Option to write out debugging information to CDCDedxTracks (DataStore objects).", true);
61  addParam("useIndividualHits", m_useIndividualHits,
62  "If using lookup table PDFs, include PDF value for each hit in likelihood. If false, the truncated mean of dedx values will be used.",
63  true);
64  addParam("ignoreMissingParticles", m_ignoreMissingParticles,
65  "Ignore particles for which no PDFs are found", false);
66  addParam("trackLevel", m_trackLevel,
67  "ONLY USEFUL FOR MC: Use track-level MC. If false, use hit-level MC", true);
68  addParam("onlyPrimaryParticles", m_onlyPrimaryParticles,
69  "ONLY USEFUL FOR MC: Only save data for primary particles", false);
70 }
71 
73 
75 {
76  if (!m_DBDedxPDFs) B2FATAL("No Dedx pdfs found in database");
77  //load dedx:momentum PDFs
78  int nBinsX, nBinsY;
79  double xMin, xMax, yMin, yMax;
80  nBinsX = nBinsY = -1;
81  xMin = xMax = yMin = yMax = 0.0;
82  for (unsigned int iPart = 0; iPart < 6; iPart++) {
83  const int pdgCode = Const::chargedStableSet.at(iPart).getPDGCode();
84  const TH2F* pdf = m_DBDedxPDFs->getCDCPDF(iPart, !m_useIndividualHits);
85 
86  if (pdf->GetEntries() == 0) {
88  continue;
89  B2FATAL("Couldn't find PDF for PDG " << pdgCode);
90  }
91 
92  //check that PDFs have the same dimensions and same binning
93  const double epsFactor = 1e-5;
94  if (nBinsX == -1 and nBinsY == -1) {
95  nBinsX = pdf->GetNbinsX();
96  nBinsY = pdf->GetNbinsY();
97  xMin = pdf->GetXaxis()->GetXmin();
98  xMax = pdf->GetXaxis()->GetXmax();
99  yMin = pdf->GetYaxis()->GetXmin();
100  yMax = pdf->GetYaxis()->GetXmax();
101  } else if (nBinsX != pdf->GetNbinsX()
102  or nBinsY != pdf->GetNbinsY()
103  or fabs(xMin - pdf->GetXaxis()->GetXmin()) > epsFactor * xMax
104  or fabs(xMax - pdf->GetXaxis()->GetXmax()) > epsFactor * xMax
105  or fabs(yMin - pdf->GetYaxis()->GetXmin()) > epsFactor * yMax
106  or fabs(yMax - pdf->GetYaxis()->GetXmax()) > epsFactor * yMax) {
107  B2FATAL("PDF for PDG " << pdgCode << " has binning/dimensions differing from previous PDF.");
108  }
109  }
110 }
111 
113 {
114 
115  // required inputs
116  m_tracks.isRequired();
118 
119  // optional inputs
121  m_tracks.optionalRelationTo(m_mcparticles);
122 
123  // register optional outputs
124  if (m_enableDebugOutput) {
125  m_dedxTracks.registerInDataStore();
126  m_tracks.registerRelationTo(m_dedxTracks);
127  }
128 
129  // register outputs
130  m_dedxLikelihoods.registerInDataStore();
131  m_tracks.registerRelationTo(m_dedxLikelihoods);
132 
133  m_DBDedxPDFs.addCallback([this]() { checkPDFs(); });
134  checkPDFs();
135 
136  // lookup table for number of wires per layer (indexed on superlayer)
137  m_nLayerWires[0] = 1280;
138  for (int i = 1; i < 9; ++i) {
139  m_nLayerWires[i] = m_nLayerWires[i - 1] + 6 * (160 + (i - 1) * 32);
140  }
141 
142  // make sure the mean and resolution parameters are reasonable
143  if (!m_DBMeanPars || m_DBMeanPars->getSize() == 0) {
144  B2WARNING("No dE/dx mean parameters!");
145  for (int i = 0; i < 15; ++i)
146  m_meanpars.push_back(1.0);
147  } else m_meanpars = m_DBMeanPars->getMeanPars();
148 
149  if (!m_DBSigmaPars || m_DBSigmaPars->getSize() == 0) {
150  B2WARNING("No dE/dx sigma parameters!");
151  for (int i = 0; i < 12; ++i)
152  m_sigmapars.push_back(1.0);
153  } else m_sigmapars = m_DBSigmaPars->getSigmaPars();
154 
155  // get the hadron correction parameters
156  if (!m_DBHadronCor || m_DBHadronCor->getSize() == 0) {
157  B2WARNING("No hadron correction parameters!");
158  for (int i = 0; i < 4; ++i)
159  m_hadronpars.push_back(0.0);
160  m_hadronpars.push_back(1.0);
161  } else m_hadronpars = m_DBHadronCor->getHadronPars();
162 
163  // create instances here to not confuse profiling
165 
166  if (!genfit::MaterialEffects::getInstance()->isInitialized()) {
167  B2FATAL("Need to have SetupGenfitExtrapolationModule in path before this one.");
168  }
169 }
170 
172 {
173  // go through Tracks
174  // get fitresult and RecoTrack and do extrapolations, save corresponding dE/dx and likelihood values
175  // get hit indices through RecoTrack::getHitPointsWithMeasurement(...)
176  // create one CDCDedxTrack per fitresult/recoTrack
177  // create one DedkLikelihood per Track (plus rel)
178 
179  // inputs
180  const int numMCParticles = m_mcparticles.getEntries();
181 
182  // get the geometry of the cdc
183  static CDCGeometryPar& cdcgeo = CDCGeometryPar::Instance();
184 
185  // **************************************************
186  //
187  // LOOP OVER TRACKS
188  //
189  // **************************************************
190 
191  m_dedxTracks.clear();
192  m_dedxLikelihoods.clear();
193 
194  int mtrack = 0;
195  for (const auto& track : m_tracks) {
196  std::shared_ptr<CDCDedxTrack> dedxTrack = std::make_shared<CDCDedxTrack>();
197  dedxTrack->m_track = mtrack++;
198 
199  // load the pion fit hypothesis or the hypothesis which is the closest in mass to a pion
200  // the tracking will not always successfully fit with a pion hypothesis
201  const TrackFitResult* fitResult = track.getTrackFitResultWithClosestMass(Const::pion);
202  if (!fitResult) {
203  B2WARNING("No related fit for track ...");
204  continue;
205  }
206 
207  if ((m_enableDebugOutput or m_onlyPrimaryParticles) and numMCParticles != 0) {
208  // find MCParticle corresponding to this track
209  const MCParticle* mcpart = track.getRelatedTo<MCParticle>();
210 
211  if (mcpart) {
213  continue; //not a primary particle, ignore
214  }
215 
216  //add some MC truths to CDCDedxTrack object
217  dedxTrack->m_pdg = mcpart->getPDG();
218  dedxTrack->m_mcmass = mcpart->getMass();
219  const MCParticle* mother = mcpart->getMother();
220  dedxTrack->m_motherPDG = mother ? mother->getPDG() : 0;
221 
222  const ROOT::Math::XYZVector trueMomentum = mcpart->getMomentum();
223  dedxTrack->m_pTrue = trueMomentum.R();
224  dedxTrack->m_cosThetaTrue = cos(trueMomentum.Theta());
225  }
226  } else {
227  dedxTrack->m_pdg = -999;
228  }
229 
230  // get momentum (at origin) from fit result
231  const ROOT::Math::XYZVector& trackMom = fitResult->getMomentum();
232  dedxTrack->m_p = trackMom.R();
233  bool nomom = (dedxTrack->m_p != dedxTrack->m_p);
234  double costh = std::cos(std::atan(1 / fitResult->getCotTheta()));
235  int charge = 1;
236  if (!nomom) {
237  costh = cos(trackMom.Theta());
238  charge = fitResult->getChargeSign();
239  }
240  dedxTrack->m_cosTheta = costh;
241  dedxTrack->m_charge = charge;
242 
243  double injring = -1.0, injtime = -1.0;
245  if (m_TTDInfo.isValid() && m_TTDInfo->hasInjection()) {
246  injring = m_TTDInfo->isHER();
247  injtime = m_TTDInfo->getTimeSinceLastInjectionInMicroSeconds();
248  }
249  dedxTrack->m_injring = injring;
250  dedxTrack->m_injtime = injtime;
251 
252  // dE/dx values will be calculated using associated RecoTrack
253  const RecoTrack* recoTrack = track.getRelatedTo<RecoTrack>();
254  if (!recoTrack) {
255  B2WARNING("No related track for this fit...");
256  continue;
257  }
258 
259  // Check to see if the track is pruned
260  if (recoTrack->getTrackFitStatus()->isTrackPruned()) {
261  B2ERROR("GFTrack is pruned, please run CDCDedxPID only on unpruned tracks! Skipping this track.");
262  continue;
263  }
264 
265  // scale factor to make electron dE/dx ~ 1
266  dedxTrack->m_scale = (m_DBScaleFactor) ? m_DBScaleFactor->getScaleFactor() : 1.0;
267 
268  // store run gains only for data!
269  bool isData = false;
270  if (m_usePrediction && numMCParticles == 0)isData = true;
271  dedxTrack->m_runGain = (m_DBRunGain && isData) ? m_DBRunGain->getRunGain() : 1.0;
272 
273  // get the cosine correction only for data!
274  dedxTrack->m_cosCor = (m_DBCosineCor && isData) ? m_DBCosineCor->getMean(costh) : 1.0;
275 
276  // get the cosine edge correction only for data!
277  bool isEdge = false;
278  if ((abs(costh + 0.860) < 0.010) || (abs(costh - 0.955) <= 0.005))isEdge = true;
279  dedxTrack->m_cosEdgeCor = (m_DBCosEdgeCor && isData && isEdge) ? m_DBCosEdgeCor->getMean(costh) : 1.0;
280 
281  bool isvalidTime = true;
282  if (injtime < 0 || injring < 0)isvalidTime = false;
283  dedxTrack->m_timeGain = (m_DBInjectTime && isData && isvalidTime) ? m_DBInjectTime->getCorrection("mean", injring, injtime) : 1.0;
284  dedxTrack->m_timeReso = (m_DBInjectTime && isData && isvalidTime) ? m_DBInjectTime->getCorrection("reso", injring, injtime) : 1.0;
285 
286  // initialize a few variables to be used in the loop over track points
287  double layerdE = 0.0; // total charge in current layer
288  double layerdx = 0.0; // total path length in current layer
289  double cdcMom = 0.0; // momentum valid in the CDC
290  int nhitscombined = 0; // number of hits combined per layer
291  int wirelongesthit = 0; // wire number of longest hit
292  double longesthit = 0; // path length of longest hit
293 
294  // loop over all CDC hits from this track
295  // Get the TrackPoints, which contain the hit information we need.
296  // Then iterate over each point.
297  const std::vector< genfit::AbsTrackRep* >& gftrackRepresentations = recoTrack->getRepresentations();
298  const std::vector< genfit::TrackPoint* >& gftrackPoints = recoTrack->getHitPointsWithMeasurement();
299  for (std::vector< genfit::TrackPoint* >::const_iterator tp = gftrackPoints.begin();
300  tp != gftrackPoints.end(); ++tp) {
301 
302  // should also be possible to use this for svd and pxd hits...
303  genfit::AbsMeasurement* aAbsMeasurementPtr = (*tp)->getRawMeasurement(0);
304  const CDCRecoHit* cdcRecoHit = dynamic_cast<const CDCRecoHit* >(aAbsMeasurementPtr);
305  if (!cdcRecoHit) continue;
306  const CDCHit* cdcHit = cdcRecoHit->getCDCHit();
307  if (!cdcHit) continue;
308 
309  // get the poca on the wire and track momentum for this hit
310  // make sure the fitter info exists
311  const genfit::AbsFitterInfo* fi = (*tp)->getFitterInfo();
312  if (!fi) {
313  B2DEBUG(29, "No fitter info, skipping...");
314  continue;
315  }
316 
317  // get the wire ID (not between 0 and 14336) and the layer info
318  WireID wireID = cdcRecoHit->getWireID();
319  const int wire = wireID.getIWire(); // use getEWire() for encoded wire number
320  int layer = cdcHit->getILayer(); // layer within superlayer
321  int superlayer = cdcHit->getISuperLayer();
322 
323  // check which algorithm found this hit
324  int foundByTrackFinder = 0;
325  const RecoHitInformation* hitInfo = recoTrack->getRecoHitInformation(cdcHit);
326  foundByTrackFinder = hitInfo->getFoundByTrackFinder();
327 
328  // add weights for hypotheses
329  double weightPionHypo = 0;
330  double weightProtHypo = 0;
331  double weightKaonHypo = 0;
332  // loop over all the present hypotheses
333  for (std::vector<genfit::AbsTrackRep* >::const_iterator trep = gftrackRepresentations.begin();
334  trep != gftrackRepresentations.end(); ++trep) {
335  const int pdgCode = TMath::Abs((*trep)->getPDG());
336  // configured to only save weights for one of these 3
337  if (!(pdgCode == Const::pion.getPDGCode() ||
338  pdgCode == Const::kaon.getPDGCode() ||
339  pdgCode == Const::proton.getPDGCode())) continue;
340  const genfit::KalmanFitterInfo* kalmanFitterInfo = (*tp)->getKalmanFitterInfo(*trep);
341  if (kalmanFitterInfo == NULL) {
342  //B2WARNING("No KalmanFitterInfo for hit in "<<pdgCode<<" track representationt. Skipping.");
343  continue;
344  }
345 
346  // there are always 2 hits, one of which is ~1, the other ~0; or both ~0. Store only the largest.
347  std::vector<double> weights = kalmanFitterInfo->getWeights();
348  const double maxWeight = weights[0] > weights[1] ? weights[0] : weights[1];
349  if (pdgCode == Const::pion.getPDGCode()) weightPionHypo = maxWeight;
350  else if (pdgCode == Const::kaon.getPDGCode()) weightKaonHypo = maxWeight;
351  else if (pdgCode == Const::proton.getPDGCode()) weightProtHypo = maxWeight;
352 
353  }
354 
355  // continuous layer number
356  int currentLayer = (superlayer == 0) ? layer : (8 + (superlayer - 1) * 6 + layer);
357  int nextLayer = currentLayer;
358 
359  // dense packed wire number (between 0 and 14336)
360  const int iwire = (superlayer == 0) ? 160 * layer + wire : m_nLayerWires[superlayer - 1] + (160 + 32 *
361  (superlayer - 1)) * layer + wire;
362 
363  // if multiple hits in a layer, we may combine the hits
364  const bool lastHit = (tp + 1 == gftrackPoints.end());
365  bool lastHitInCurrentLayer = lastHit;
366  if (!lastHit) {
367  // peek at next hit
368  genfit::AbsMeasurement* aAbsMeasurementPtrNext = (*(tp + 1))->getRawMeasurement(0);
369  const CDCRecoHit* nextcdcRecoHit = dynamic_cast<const CDCRecoHit* >(aAbsMeasurementPtrNext);
370  // if next hit fails, assume this is the last hit in the layer
371  if (!nextcdcRecoHit || !(cdcRecoHit->getCDCHit()) || !((*(tp + 1))->getFitterInfo())) {
372  lastHitInCurrentLayer = true;
373  break;
374  }
375  const CDCHit* nextcdcHit = nextcdcRecoHit->getCDCHit();
376  const int nextILayer = nextcdcHit->getILayer();
377  const int nextSuperlayer = nextcdcHit->getISuperLayer();
378  nextLayer = (nextSuperlayer == 0) ? nextILayer : (8 + (nextSuperlayer - 1) * 6 + nextILayer);
379  lastHitInCurrentLayer = (nextLayer != currentLayer);
380  }
381 
382  // find the position of the endpoints of the sense wire
383  const TVector3& wirePosF = cdcgeo.wireForwardPosition(wireID, CDCGeometryPar::c_Aligned);
384  const TVector3& wirePosB = cdcgeo.wireBackwardPosition(wireID, CDCGeometryPar::c_Aligned);
385  const TVector3 wireDir = (wirePosB - wirePosF).Unit();
386 
387  int nWires = cdcgeo.nWiresInLayer(currentLayer);
388 
389  // radii of field wires for this layer
390  double inner = cdcgeo.innerRadiusWireLayer()[currentLayer];
391  double outer = cdcgeo.outerRadiusWireLayer()[currentLayer];
392 
393  double topHeight = outer - wirePosF.Perp();
394  double bottomHeight = wirePosF.Perp() - inner;
395  double cellHeight = topHeight + bottomHeight;
396  double topHalfWidth = M_PI * outer / nWires;
397  double bottomHalfWidth = M_PI * inner / nWires;
398  double cellHalfWidth = M_PI * wirePosF.Perp() / nWires;
399 
400  // first construct the boundary lines, then create the cell
401  const DedxPoint tl = DedxPoint(-topHalfWidth, topHeight);
402  const DedxPoint tr = DedxPoint(topHalfWidth, topHeight);
403  const DedxPoint br = DedxPoint(bottomHalfWidth, -bottomHeight);
404  const DedxPoint bl = DedxPoint(-bottomHalfWidth, -bottomHeight);
405  DedxDriftCell c = DedxDriftCell(tl, tr, br, bl);
406 
407  // make sure the MOP is reasonable (an exception is thrown for bad numerics)
408  try {
409  const genfit::MeasuredStateOnPlane& mop = fi->getFittedState();
410 
411  // use the MOP to determine the DOCA and entrance angle
412  B2Vector3D fittedPoca = mop.getPos();
413  const TVector3& pocaMom = mop.getMom();
414  if (tp == gftrackPoints.begin() || cdcMom == 0) {
415  cdcMom = pocaMom.Mag();
416  dedxTrack->m_pCDC = cdcMom;
417  }
418  if (nomom)
419  dedxTrack->m_p = cdcMom;
420 
421  // get the doca and entrance angle information.
422  // constructPlane places the coordinate center in the POCA to the
423  // wire. Using this is the default behavior. If this should be too
424  // slow, as it has to re-evaluate the POCA
425  // B2Vector3D pocaOnWire = cdcRecoHit->constructPlane(mop)->getO();
426 
427  // uses the plane determined by the track fit.
428  B2Vector3D pocaOnWire = mop.getPlane()->getO(); // DOUBLE CHECK THIS --\/
429 
430  // The vector from the wire to the track.
431  B2Vector3D B2WireDoca = fittedPoca - pocaOnWire;
432 
433  // the sign of the doca is defined here to be positive in the +x dir in the cell
434  double doca = B2WireDoca.Perp();
435  double phidiff = fittedPoca.Phi() - pocaOnWire.Phi();
436  // be careful about "wrap around" cases when the poca and wire are close, but
437  // the difference in phi is largy
438  if (phidiff > -3.1416 && (phidiff < 0 || phidiff > 3.1416)) doca *= -1;
439 
440  // The opening angle of the track momentum direction
441  const double px = pocaMom.X();
442  const double py = pocaMom.Y();
443  const double wx = pocaOnWire.X();
444  const double wy = pocaOnWire.Y();
445  const double cross = wx * py - wy * px;
446  const double dot = wx * px + wy * py;
447  double entAng = atan2(cross, dot);
448 
449  // re-scaled (RS) doca and entAng variable: map to square cell
450  double cellR = 2 * cellHalfWidth / cellHeight;
451  double tana = 100.0;
452  if (std::abs(2 * atan(1) - std::abs(entAng)) < 0.01)tana = 100 * (entAng / std::abs(entAng)); //avoid infinity at pi/2
453  else tana = std::tan(entAng);
454  double docaRS = doca * std::sqrt((1 + cellR * cellR * tana * tana) / (1 + tana * tana));
455  double entAngRS = std::atan(tana / cellR);
456 
458  int adcbaseCount = cdcHit->getADCCount(); // pedestal subtracted?
459  int adcCount = (m_DBNonlADC && m_usePrediction
460  && numMCParticles == 0) ? m_DBNonlADC->getCorrectedADC(adcbaseCount, currentLayer) : adcbaseCount;
461 
462  double hitCharge = translator.getCharge(adcCount, wireID, false, pocaOnWire.Z(), pocaMom.Phi());
463  int driftT = cdcHit->getTDCCount();
464 
465  // we want electrons to be one, so artificially scale the adcCount
466  double dadcCount = 1.0 * adcCount;
467  if (dedxTrack->m_scale != 0) dadcCount /= dedxTrack->m_scale;
468 
469  RealisticTDCCountTranslator realistictdc;
470  double driftDRealistic = realistictdc.getDriftLength(driftT, wireID, 0, true, pocaOnWire.Z(), pocaMom.Phi(), pocaMom.Theta());
471  double driftDRealisticRes = realistictdc.getDriftLengthResolution(driftDRealistic, wireID, true, pocaOnWire.Z(), pocaMom.Phi(),
472  pocaMom.Theta());
473 
474  // now calculate the path length for this hit
475  double celldx = c.dx(doca, entAng);
476  if (c.isValid()) {
477  // get the wire gain constant
478  double wiregain = (m_DBWireGains && m_usePrediction && numMCParticles == 0) ? m_DBWireGains->getWireGain(iwire) : 1.0;
479 
480  //normalization of rescaled doca wrt cell size for layer dependent 2D corrections
481  double normDocaRS = docaRS / cellHalfWidth;
482  double twodcor = (m_DB2DCell && m_usePrediction
483  && numMCParticles == 0) ? m_DB2DCell->getMean(currentLayer, normDocaRS, entAngRS) : 1.0;
484 
485  // get the 1D cleanup correction
486  double onedcor = (m_DB1DCell && m_usePrediction && numMCParticles == 0) ? m_DB1DCell->getMean(currentLayer, entAngRS) : 1.0;
487 
488  // apply the calibration to dE to propagate to both hit and layer measurements
489  // Note: could move the sin(theta) here since it is common accross the track
490  // It is applied in two places below (hit level and layer level)
491  double correction = dedxTrack->m_runGain * dedxTrack->m_cosCor * dedxTrack->m_cosEdgeCor * dedxTrack->m_timeGain * wiregain *
492  twodcor * onedcor;
493 
494  // --------------------
495  // save individual hits (even for dead wires)
496  // --------------------
497  if (correction != 0) dadcCount = dadcCount / correction;
498  else dadcCount = 0;
499 
500  double cellDedx = (dadcCount / celldx);
501 
502  // correct for path length through the cell
503  if (nomom) cellDedx *= std::sin(std::atan(1 / fitResult->getCotTheta()));
504  else cellDedx *= std::sin(trackMom.Theta());
505 
507  dedxTrack->addHit(wire, iwire, currentLayer, doca, docaRS, entAng, entAngRS,
508  adcCount, adcbaseCount, hitCharge, celldx, cellDedx, cellHeight, cellHalfWidth, driftT,
509  driftDRealistic, driftDRealisticRes, wiregain, twodcor, onedcor,
510  foundByTrackFinder, weightPionHypo, weightKaonHypo, weightProtHypo);
511 
512  // --------------------
513  // save layer hits only with active wires
514  // --------------------
515  if (correction != 0) {
516 
517  layerdE += dadcCount;
518  layerdx += celldx;
519 
520  if (celldx > longesthit) {
521  longesthit = celldx;
522  wirelongesthit = iwire;
523  }
524  nhitscombined++;
525  }
526  }
527  } catch (genfit::Exception&) {
528  B2WARNING("Track: " << mtrack << ": genfit::MeasuredStateOnPlane exception...");
529  continue;
530  }
531 
532  // check if there are any more hits in this layer
533  if (lastHitInCurrentLayer) {
534  if (layerdx > 0) {
535  double totalDistance;
536  if (nomom) totalDistance = layerdx / std::sin(std::atan(1 / fitResult->getCotTheta()));
537  else totalDistance = layerdx / std::sin(trackMom.Theta());
538  double layerDedx = layerdE / totalDistance;
539 
540  // save the information for this layer
541  if (layerDedx > 0) {
542  dedxTrack->addDedx(nhitscombined, wirelongesthit, currentLayer, totalDistance, layerDedx);
543  // save the PID information if using individual hits
544  if (m_useIndividualHits) {
545  // use the momentum valid in the cdc
546  saveLookupLogl(dedxTrack->m_cdcLogl, dedxTrack->m_pCDC, layerDedx);
547  }
548  }
549  }
550  // stop when the track starts to curl
551  if (!m_backHalfCurlers && nextLayer < currentLayer) break;
552 
553  layerdE = 0;
554  layerdx = 0;
555  nhitscombined = 0;
556  wirelongesthit = 0;
557  longesthit = 0;
558  }
559  } // end of loop over CDC hits for this track
560 
561  // Determine the number of hits to be used
562  //m_lDedx is a ector for layerDedx and created w/ ->adddedx method above
563  if (dedxTrack->m_lDedx.empty()) {
564  B2DEBUG(29, "Found track with no hits, ignoring.");
565  continue;
566  } else {
567  // determine the number of hits for this track (used below)
568  const int numDedx = dedxTrack->m_lDedx.size();
569  // add a factor of 0.51 here to make sure we are rounding appropriately...
570  const int lowEdgeTrunc = int(numDedx * m_removeLowest + 0.51);
571  const int highEdgeTrunc = int(numDedx * (1 - m_removeHighest) + 0.51);
572  dedxTrack->m_lNHitsUsed = highEdgeTrunc - lowEdgeTrunc;
573  }
574 
575  // Get the truncated mean
576  //
577  // If using track-level MC, get the predicted mean and resolution and throw a random
578  // number to get the simulated dE/dx truncated mean. Otherwise, calculate the truncated
579  // mean from the simulated hits (hit-level MC).
581  calculateMeans(&(dedxTrack->m_dedxAvg),
582  &(dedxTrack->m_dedxAvgTruncatedNoSat),
583  &(dedxTrack->m_dedxAvgTruncatedErr),
584  dedxTrack->m_lDedx);
585 
586  // apply the "hadron correction" only to data
587  if (numMCParticles == 0)
588  dedxTrack->m_dedxAvgTruncated = D2I(costh, I2D(costh, 1.00) / 1.00 * dedxTrack->m_dedxAvgTruncatedNoSat);
589  else dedxTrack->m_dedxAvgTruncated = dedxTrack->m_dedxAvgTruncatedNoSat;
590  }
591 
592  // If this is a MC track, get the track-level dE/dx
593  if (numMCParticles != 0 && dedxTrack->m_mcmass > 0 && dedxTrack->m_pTrue != 0) {
594  // determine the predicted mean and resolution
595  double mean = getMean(dedxTrack->m_pCDC / dedxTrack->m_mcmass);
596  double sigma = getSigma(mean, dedxTrack->m_lNHitsUsed,
597  dedxTrack->m_cosTheta, dedxTrack->m_timeReso);
598  dedxTrack->m_simDedx = gRandom->Gaus(mean, sigma);
599  while (dedxTrack->m_simDedx < 0)
600  dedxTrack->m_simDedx = gRandom->Gaus(mean, sigma);
601  if (m_trackLevel)
602  dedxTrack->m_dedxAvgTruncated = dedxTrack->m_simDedx;
603  }
604 
605  // save the PID information for both lookup tables and parameterized means and resolutions
606  saveChiValue(dedxTrack->m_cdcChi, dedxTrack->m_predmean, dedxTrack->m_predres, dedxTrack->m_pCDC, dedxTrack->m_dedxAvgTruncated,
607  dedxTrack->m_cosTheta, dedxTrack->m_lNHitsUsed, dedxTrack->m_timeReso);
608  if (!m_useIndividualHits)
609  saveLookupLogl(dedxTrack->m_cdcLogl, dedxTrack->m_pCDC, dedxTrack->m_dedxAvgTruncated);
610 
611  // save CDCDedxLikelihood
612  // use parameterized method if called or if pdf file for lookup tables are empty
613  double pidvalues[Const::ChargedStable::c_SetSize];
615  if (m_usePrediction) {
616  for (const Const::ChargedStable pdgIter : set) {
617  pidvalues[pdgIter.getIndex()] = -0.5 * dedxTrack->m_cdcChi[pdgIter.getIndex()] * dedxTrack->m_cdcChi[pdgIter.getIndex()];
618  }
619  } else {
620  for (const Const::ChargedStable pdgIter : set) {
621  pidvalues[pdgIter.getIndex()] = dedxTrack->m_cdcLogl[pdgIter.getIndex()];
622  }
623  }
624 
625  CDCDedxLikelihood* likelihoodObj = m_dedxLikelihoods.appendNew(pidvalues);
626  track.addRelationTo(likelihoodObj);
627 
628  if (m_enableDebugOutput) {
629  // book the information for this track
630  CDCDedxTrack* newCDCDedxTrack = m_dedxTracks.appendNew(*dedxTrack);
631  track.addRelationTo(newCDCDedxTrack);
632  }
633 
634  } // end of loop over tracks
635 }
636 
638 {
639 
640  B2DEBUG(29, "CDCDedxPIDModule exiting");
641 }
642 
643 void CDCDedxPIDModule::calculateMeans(double* mean, double* truncatedMean, double* truncatedMeanErr,
644  const std::vector<double>& dedx) const
645 {
646  // Calculate the truncated average by skipping the lowest & highest
647  // events in the array of dE/dx values
648  std::vector<double> sortedDedx = dedx;
649  std::sort(sortedDedx.begin(), sortedDedx.end());
650  sortedDedx.erase(std::remove(sortedDedx.begin(), sortedDedx.end(), 0), sortedDedx.end());
651  sortedDedx.shrink_to_fit();
652 
653  double truncatedMeanTmp = 0.0;
654  double meanTmp = 0.0;
655  double sumOfSquares = 0.0;
656  int numValuesTrunc = 0;
657  const int numDedx = sortedDedx.size();
658 
659  // add a factor of 0.51 here to make sure we are rounding appropriately...
660  const int lowEdgeTrunc = int(numDedx * m_removeLowest + 0.51);
661  const int highEdgeTrunc = int(numDedx * (1 - m_removeHighest) + 0.51);
662  for (int i = 0; i < numDedx; i++) {
663  meanTmp += sortedDedx[i];
664  if (i >= lowEdgeTrunc and i < highEdgeTrunc) {
665  truncatedMeanTmp += sortedDedx[i];
666  sumOfSquares += sortedDedx[i] * sortedDedx[i];
667  numValuesTrunc++;
668  }
669  }
670 
671  if (numDedx != 0) {
672  meanTmp /= numDedx;
673  }
674  if (numValuesTrunc != 0) {
675  truncatedMeanTmp /= numValuesTrunc;
676  } else {
677  truncatedMeanTmp = meanTmp;
678  }
679 
680  *mean = meanTmp;
681  *truncatedMean = truncatedMeanTmp;
682 
683  if (numValuesTrunc > 1) {
684  *truncatedMeanErr = sqrt(sumOfSquares / double(numValuesTrunc) - truncatedMeanTmp * truncatedMeanTmp) / double(
685  numValuesTrunc - 1);
686  } else {
687  *truncatedMeanErr = 0;
688  }
689 }
690 
691 void CDCDedxPIDModule::saveLookupLogl(double(&logl)[Const::ChargedStable::c_SetSize], double p, double dedx)
692 {
693  //all pdfs have the same dimensions
694  const TH2F* pdf = m_DBDedxPDFs->getCDCPDF(0, !m_useIndividualHits);
695  const Int_t binX = pdf->GetXaxis()->FindFixBin(p);
696  const Int_t binY = pdf->GetYaxis()->FindFixBin(dedx);
697 
698  for (unsigned int iPart = 0; iPart < Const::ChargedStable::c_SetSize; iPart++) {
699  pdf = m_DBDedxPDFs->getCDCPDF(iPart, !m_useIndividualHits);
700  if (pdf->GetEntries() == 0) { //might be NULL if m_ignoreMissingParticles is set
701  B2WARNING("NO CDC PDFS...");
702  continue;
703  }
704  double probability = 0.0;
705 
706  //check if this is still in the histogram, take overflow bin otherwise
707  if (binX < 1 or binX > pdf->GetNbinsX()
708  or binY < 1 or binY > pdf->GetNbinsY()) {
709  probability = pdf->GetBinContent(binX, binY);
710  } else {
711  //in normal histogram range. Of course ROOT has a bug that Interpolate()
712  //is not declared as const but it does not modify the internal state so
713  //fine, const_cast it is.
714  probability = const_cast<TH2F*>(pdf)->Interpolate(p, dedx);
715  }
716 
717  if (probability != probability)
718  B2ERROR("probability NAN for a track with p=" << p << " and dedx=" << dedx);
719 
720  //my pdfs aren't perfect...
721  if (probability == 0.0)
722  probability = m_useIndividualHits ? (1e-5) : (1e-3); //likelihoods for truncated mean are much higher
723  logl[iPart] += log(probability);
724  }
725 }
726 
727 double CDCDedxPIDModule::D2I(const double cosTheta, const double D) const
728 {
729  double absCosTheta = fabs(cosTheta);
730  double projection = pow(absCosTheta, m_hadronpars[3]) + m_hadronpars[2];
731  if (projection == 0) {
732  B2WARNING("Something wrong with dE/dx hadron constants!");
733  return D;
734  }
735 
736  double chargeDensity = D / projection;
737  double numerator = 1 + m_hadronpars[0] * chargeDensity;
738  double denominator = 1 + m_hadronpars[1] * chargeDensity;
739 
740  if (denominator == 0) {
741  B2WARNING("Something wrong with dE/dx hadron constants!");
742  return D;
743  }
744 
745  double I = D * m_hadronpars[4] * numerator / denominator;
746  return I;
747 }
748 
749 double CDCDedxPIDModule::I2D(const double cosTheta, const double I) const
750 {
751  double absCosTheta = fabs(cosTheta);
752  double projection = pow(absCosTheta, m_hadronpars[3]) + m_hadronpars[2];
753 
754  if (projection == 0 || m_hadronpars[4] == 0) {
755  B2WARNING("Something wrong with dE/dx hadron constants!");
756  return I;
757  }
758 
759  double a = m_hadronpars[0] / projection;
760  double b = 1 - m_hadronpars[1] / projection * (I / m_hadronpars[4]);
761  double c = -1.0 * I / m_hadronpars[4];
762 
763  if (b == 0 && a == 0) {
764  B2WARNING("both a and b coefficiants for hadron correction are 0");
765  return I;
766  }
767 
768  double discr = b * b - 4.0 * a * c;
769  if (discr < 0) {
770  B2WARNING("negative discriminant; return uncorrectecd value");
771  return I;
772  }
773 
774  double D = (a != 0) ? (-b + sqrt(discr)) / (2.0 * a) : -c / b;
775  if (D < 0) {
776  B2WARNING("D is less 0! will try another solution");
777  D = (a != 0) ? (-b - sqrt(discr)) / (2.0 * a) : -c / b;
778  if (D < 0) {
779  B2WARNING("D is still less 0! just return uncorrectecd value");
780  return I;
781  }
782  }
783 
784  return D;
785 }
786 
787 double CDCDedxPIDModule::meanCurve(double* x, double* par, int version) const
788 {
789  // calculate the predicted mean value as a function of beta-gamma (bg)
790  // this is done with a different function depending on the value of bg
791  double f = 0;
792 
793  if (version == 0) {
794  if (par[0] == 1)
795  f = par[1] * std::pow(std::sqrt(x[0] * x[0] + 1), par[3]) / std::pow(x[0], par[3]) *
796  (par[2] - par[5] * std::log(1 / x[0])) - par[4] + std::exp(par[6] + par[7] * x[0]);
797  else if (par[0] == 2)
798  f = par[1] * std::pow(x[0], 3) + par[2] * x[0] * x[0] + par[3] * x[0] + par[4];
799  else if (par[0] == 3)
800  f = -1.0 * par[1] * std::log(par[4] + std::pow(1 / x[0], par[2])) + par[3];
801  }
802 
803  return f;
804 }
805 
806 double CDCDedxPIDModule::getMean(double bg) const
807 {
808  // define the section of the mean to use
809  double A = 0, B = 0, C = 0;
810  if (bg < 4.5)
811  A = 1;
812  else if (bg < 10)
813  B = 1;
814  else
815  C = 1;
816 
817  double x[1]; x[0] = bg;
818  double parsA[9];
819  double parsB[5];
820  double parsC[5];
821 
822  parsA[0] = 1; parsB[0] = 2; parsC[0] = 3;
823  for (int i = 0; i < 15; ++i) {
824  if (i < 7) parsA[i + 1] = m_meanpars[i];
825  else if (i < 11) parsB[i % 7 + 1] = m_meanpars[i];
826  else parsC[i % 11 + 1] = m_meanpars[i];
827  }
828 
829  // calculate dE/dx from the Bethe-Bloch mean
830  double partA = meanCurve(x, parsA, 0);
831  double partB = meanCurve(x, parsB, 0);
832  double partC = meanCurve(x, parsC, 0);
833 
834  return (A * partA + B * partB + C * partC);
835 }
836 
837 double CDCDedxPIDModule::sigmaCurve(double* x, const double* par, int version) const
838 {
839  // calculate the predicted mean value as a function of beta-gamma (bg)
840  // this is done with a different function depending dE/dx, nhit, and sin(theta)
841  double f = 0;
842 
843  if (version == 0) {
844  if (par[0] == 1) { // return dedx parameterization
845  f = par[1] + par[2] * x[0];
846  } else if (par[0] == 2) { // return nhit or sin(theta) parameterization
847  f = par[1] * std::pow(x[0], 4) + par[2] * std::pow(x[0], 3) +
848  par[3] * x[0] * x[0] + par[4] * x[0] + par[5];
849  } else if (par[0] == 3) { // return cos(theta) parameterization
850  f = par[1] * exp(-0.5 * pow(((x[0] - par[2]) / par[3]), 2)) +
851  par[4] * pow(x[0], 6) + par[5] * pow(x[0], 5) + par[6] * pow(x[0], 4) +
852  par[7] * pow(x[0], 3) + par[8] * x[0] * x[0] + par[9] * x[0] + par[10];
853  }
854  }
855 
856  return f;
857 }
858 
859 
860 double CDCDedxPIDModule::getSigma(double dedx, double nhit, double cos, double timereso) const
861 {
862 
863  double x[1];
864  double dedxpar[3];
865  double nhitpar[6];
866  double cospar[11];
867 
868  dedxpar[0] = 1; nhitpar[0] = 2; cospar[0] = 3;
869  for (int i = 0; i < 10; ++i) {
870  if (i < 2) dedxpar[i + 1] = m_sigmapars[i];
871  if (i < 5) nhitpar[i + 1] = m_sigmapars[i + 2];
872  cospar[i + 1] = m_sigmapars[i + 7];
873  }
874 
875  // determine sigma from the parameterization
876  x[0] = dedx;
877  double corDedx = sigmaCurve(x, dedxpar, 0);
878 
879  x[0] = nhit;
880  double corNHit;
881  int nhit_min = 8, nhit_max = 37;
882 
883  if (nhit < nhit_min) {
884  x[0] = nhit_min;
885  corNHit = sigmaCurve(x, nhitpar, 0) * sqrt(nhit_min / nhit);
886  } else if (nhit > nhit_max) {
887  x[0] = nhit_max;
888  corNHit = sigmaCurve(x, nhitpar, 0) * sqrt(nhit_max / nhit);
889  } else corNHit = sigmaCurve(x, nhitpar, 0);
890 
891  x[0] = cos;
892  double corCos = sigmaCurve(x, cospar, 0);
893 
894  return (corDedx * corCos * corNHit * timereso);
895 }
896 
898  double(&predmean)[Const::ChargedStable::c_SetSize], double(&predsigma)[Const::ChargedStable::c_SetSize], double p, double dedx,
899  double cos, int nhit, double timereso) const
900 {
901  // determine a chi value for each particle type
903  for (const Const::ChargedStable pdgIter : set) {
904  double bg = p / pdgIter.getMass();
905 
906  // determine the predicted mean and resolution
907  double mean = getMean(bg);
908  double sigma = getSigma(mean, nhit, cos, timereso);
909 
910  predmean[pdgIter.getIndex()] = mean;
911  predsigma[pdgIter.getIndex()] = sigma;
912 
913  // fill the chi value for this particle type
914  if (sigma != 0) chi[pdgIter.getIndex()] = ((dedx - mean) / (sigma));
915  }
916 }
DataType Phi() const
The azimuth angle.
Definition: B2Vector3.h:151
DataType Z() const
access variable Z (= .at(2) without boundary check)
Definition: B2Vector3.h:435
DataType X() const
access variable X (= .at(0) without boundary check)
Definition: B2Vector3.h:431
DataType Y() const
access variable Y (= .at(1) without boundary check)
Definition: B2Vector3.h:433
DataType Perp() const
The transverse component (R in cylindrical coordinate system).
Definition: B2Vector3.h:200
Container for likelihoods obtained by the CDC dE/dx PID (CDCDedxPIDModule).
double I2D(double cosTheta, double I) const
hadron saturation parameterization part 1
double D2I(double cosTheta, double D) const
hadron saturation parameterization part 2
double getMean(double bg) const
calculate the predicted mean using the parameterized resolution
virtual ~CDCDedxPIDModule()
Destructor.
std::vector< double > m_hadronpars
hadron saturation parameters
DBObjPtr< CDCDedxRunGain > m_DBRunGain
Run gain DB object.
double sigmaCurve(double *x, const double *par, int version) const
parameterized resolution for predictions
DBObjPtr< CDCDedxMeanPars > m_DBMeanPars
dE/dx mean parameters
virtual void initialize() override
Initialize the module.
DBObjPtr< CDCDedxHadronCor > m_DBHadronCor
hadron saturation parameters
virtual void event() override
This method is called for each event.
double m_removeHighest
Portion of highest dE/dx values that should be discarded for truncated mean.
StoreArray< CDCDedxLikelihood > m_dedxLikelihoods
Output array of CDCDedxLikelihoods.
DBObjPtr< CDCDedxCosineEdge > m_DBCosEdgeCor
non-lineary ACD correction DB object
StoreArray< MCParticle > m_mcparticles
Optional array of input MCParticles.
void saveLookupLogl(double(&logl)[Const::ChargedStable::c_SetSize], double p, double dedx)
for all particles, save log-likelihood values into 'logl'.
DBObjPtr< CDCDedxADCNonLinearity > m_DBNonlADC
non-lineary ACD correction DB object
DBObjPtr< CDCDedx1DCell > m_DB1DCell
1D correction DB object
void checkPDFs()
Check the pdfs for consistency everytime they change in the database.
virtual void terminate() override
End of the event processing.
void saveChiValue(double(&chi)[Const::ChargedStable::c_SetSize], double(&predmean)[Const::ChargedStable::c_SetSize], double(&predres)[Const::ChargedStable::c_SetSize], double p, double dedx, double cos, int nhit, double timereso) const
for all particles, save chi values into 'chi'.
double meanCurve(double *x, double *par, int version) const
parameterized beta-gamma curve for predicted means
std::vector< double > m_sigmapars
dE/dx resolution parameters
void calculateMeans(double *mean, double *truncatedMean, double *truncatedMeanErr, const std::vector< double > &dedx) const
Save arithmetic and truncated mean for the 'dedx' values.
DBObjPtr< CDCDedx2DCell > m_DB2DCell
2D correction DB object
double getSigma(double dedx, double nhit, double cos, double timereso) const
calculate the predicted resolution using the parameterized resolution
DBObjPtr< CDCDedxCosineCor > m_DBCosineCor
Electron saturation correction DB object.
bool m_ignoreMissingParticles
Ignore particles for which no PDFs are found.
StoreArray< Track > m_tracks
Required array of input Tracks.
int m_nLayerWires[9]
number of wires per layer: needed for wire gain calibration
CDCDedxPIDModule()
Default constructor.
bool m_onlyPrimaryParticles
Only save data for primary particles (as determined by MC truth)
DBObjPtr< CDCDedxSigmaPars > m_DBSigmaPars
dE/dx resolution parameters
DBObjPtr< CDCDedxWireGain > m_DBWireGains
Wire gain DB object.
std::vector< double > m_meanpars
dE/dx mean parameters
bool m_backHalfCurlers
Whether to use the back half of curlers.
bool m_trackLevel
Whether to use track-level or hit-level MC.
StoreArray< RecoTrack > m_recoTracks
Required array of input RecoTracks.
bool m_useIndividualHits
Include PDF value for each hit in likelihood.
bool m_usePrediction
Whether to use parameterized means and resolutions or lookup tables.
double m_removeLowest
Portion of lowest dE/dx values that should be discarded for truncated mean.
StoreArray< CDCDedxTrack > m_dedxTracks
Output array of CDCDedxTracks.
bool m_enableDebugOutput
Whether to save information on tracks and associated hits and dE/dx values in DedxTrack objects.
DBObjPtr< CDCDedxInjectionTime > m_DBInjectTime
time gain/reso DB object
DBObjPtr< CDCDedxScaleFactor > m_DBScaleFactor
Scale factor to make electrons ~1.
DBObjPtr< DedxPDFs > m_DBDedxPDFs
DB object for dedx:momentum PDFs.
Debug output for CDCDedxPID module.
Definition: CDCDedxTrack.h:25
Class containing the result of the unpacker in raw data and the result of the digitizer in simulation...
Definition: CDCHit.h:40
short getTDCCount() const
Getter for TDC count.
Definition: CDCHit.h:219
unsigned short getADCCount() const
Getter for integrated charge.
Definition: CDCHit.h:230
unsigned short getISuperLayer() const
Getter for iSuperLayer.
Definition: CDCHit.h:184
unsigned short getILayer() const
Getter for iLayer.
Definition: CDCHit.h:172
This class is used to transfer CDC information to the track fit.
Definition: CDCRecoHit.h:32
const CDCHit * getCDCHit() const
get the pointer to the CDCHit object that was used to create this CDCRecoHit object.
Definition: CDCRecoHit.h:112
WireID getWireID() const
Getter for WireID object.
Definition: CDCRecoHit.h:49
The Class for CDC Geometry Parameters.
const B2Vector3D wireForwardPosition(uint layerId, int cellId, EWirePosition set=c_Base) const
Returns the forward position of the input sense wire.
const B2Vector3D wireBackwardPosition(uint layerId, int cellId, EWirePosition set=c_Base) const
Returns the backward position of the input sense wire.
unsigned nWiresInLayer(int layerId) const
Returns wire numbers in a layer.
const double * innerRadiusWireLayer() const
Returns an array of inner radius of wire layers.
static CDCGeometryPar & Instance(const CDCGeometry *=nullptr)
Static method to get a reference to the CDCGeometryPar instance.
const double * outerRadiusWireLayer() const
Returns an array of outer radius of wire layers.
This class simply assumes a linear translation through (0,0)
float getCharge(unsigned short adcCount, const WireID &, bool, float, float)
just multiply with the conversion factor and return.
Translator mirroring the realistic Digitization.
double getDriftLength(unsigned short tdcCount, const WireID &wireID=WireID(), double timeOfFlightEstimator=0, bool leftRight=false, double z=0, double alpha=0, double theta=static_cast< double >(TMath::Pi()/2.), unsigned short adcCount=0) override
Get Drift length.
double getDriftLengthResolution(double driftLength, const WireID &wireID=WireID(), bool leftRight=false, double z=0, double alpha=0, double=static_cast< double >(TMath::Pi()/2.)) override
Get position resolution^2 corresponding to the drift length from getDriftLength of this class.
Provides a type-safe way to pass members of the chargedStableSet set.
Definition: Const.h:580
static const unsigned int c_SetSize
Number of elements (for use in array bounds etc.)
Definition: Const.h:606
A set of ParticleType objects, with defined order.
Definition: Const.h:508
const ParticleType & at(unsigned int index) const
Return particle at given index, or end() if out of range.
Definition: Const.h:540
int getPDGCode() const
PDG code.
Definition: Const.h:464
static const ParticleSet chargedStableSet
set of charged stable particles
Definition: Const.h:609
static const ChargedStable pion
charged pion particle
Definition: Const.h:652
static const ChargedStable proton
proton particle
Definition: Const.h:654
static const ChargedStable kaon
charged kaon particle
Definition: Const.h:653
A class to hold the geometry of a cell.
Definition: LineHelper.h:186
A collection of classes that are useful for making a simple path length correction to the dE/dx measu...
Definition: LineHelper.h:29
A Class to store the Monte Carlo particle information.
Definition: MCParticle.h:32
@ c_PrimaryParticle
bit 0: Particle is primary particle.
Definition: MCParticle.h:47
float getMass() const
Return the particle mass in GeV.
Definition: MCParticle.h:135
bool hasStatus(unsigned short int bitmask) const
Return if specific status bit is set.
Definition: MCParticle.h:129
int m_pdg
PDG-Code of the particle.
Definition: MCParticle.h:541
int getPDG() const
Return PDG code of particle.
Definition: MCParticle.h:112
ROOT::Math::XYZVector getMomentum() const
Return momentum.
Definition: MCParticle.h:198
Base class for Modules.
Definition: Module.h:72
void setDescription(const std::string &description)
Sets the description of the module.
Definition: Module.cc:214
void setPropertyFlags(unsigned int propertyFlags)
Sets the flags for the module properties.
Definition: Module.cc:208
@ c_ParallelProcessingCertified
This module can be run in parallel processing mode safely (All I/O must be done through the data stor...
Definition: Module.h:80
This class stores additional information to every CDC/SVD/PXD hit stored in a RecoTrack.
OriginTrackFinder getFoundByTrackFinder() const
Get which track finder has found the track.
This is the Reconstruction Event-Data Model Track.
Definition: RecoTrack.h:79
const genfit::FitStatus * getTrackFitStatus(const genfit::AbsTrackRep *representation=nullptr) const
Return the track fit status for the given representation or for the cardinal one. You are not allowed...
Definition: RecoTrack.h:621
const std::vector< genfit::TrackPoint * > & getHitPointsWithMeasurement() const
Return a list of measurements and track points, which can be used e.g. to extrapolate....
Definition: RecoTrack.h:708
const std::vector< genfit::AbsTrackRep * > & getRepresentations() const
Return a list of track representations. You are not allowed to modify or delete them!
Definition: RecoTrack.h:638
RecoHitInformation * getRecoHitInformation(HitType *hit) const
Return the reco hit information for a generic hit from the storeArray.
Definition: RecoTrack.h:312
bool isRequired(const std::string &name="")
Ensure this array/object has been registered previously.
bool isOptional(const std::string &name="")
Tell the DataStore about an optional input.
int getEntries() const
Get the number of objects in the array.
Definition: StoreArray.h:216
Type-safe access to single objects in the data store.
Definition: StoreObjPtr.h:96
bool isValid() const
Check whether the object was created.
Definition: StoreObjPtr.h:111
Values of the result of a track fit with a given particle hypothesis.
short getChargeSign() const
Return track charge (1 or -1).
double getCotTheta() const
Getter for tanLambda with CDF naming convention.
ROOT::Math::XYZVector getMomentum() const
Getter for vector of momentum at closest approach of track in r/phi projection.
The Unit class.
Definition: Unit.h:40
Class to identify a wire inside the CDC.
Definition: WireID.h:34
unsigned short getIWire() const
Getter for wire within the layer.
Definition: WireID.h:145
This class collects all information needed and produced by a specific AbsFitter and is specific to on...
Definition: AbsFitterInfo.h:42
Contains the measurement and covariance in raw detector coordinates.
Exception class for error handling in GENFIT (provides storage for diagnostic information)
Definition: Exception.h:48
bool isTrackPruned() const
Has the track been pruned after the fit?
Definition: FitStatus.h:116
Collects information needed and produced by a AbsKalmanFitter implementations and is specific to one ...
std::vector< double > getWeights() const
Get weights of measurements.
#StateOnPlane with additional covariance matrix.
REG_MODULE(arichBtest)
Register the Module.
void addParam(const std::string &name, T &paramVariable, const std::string &description, const T &defaultValue)
Adds a new parameter to the module.
Definition: Module.h:560
double sqrt(double a)
sqrt for double
Definition: beamHelpers.h:28
double atan(double a)
atan for double
Definition: beamHelpers.h:34
T dot(GeneralVector< T > a, GeneralVector< T > b)
dot product of two general vectors
Definition: beamHelpers.h:163
double tan(double a)
tan for double
Definition: beamHelpers.h:31
MCParticle * getMother() const
Returns a pointer to the mother particle.
Definition: MCParticle.h:600
Abstract base class for different kinds of events.