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