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