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 <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
37using namespace Belle2;
38using namespace CDC;
39using namespace Dedx;
40
41REG_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
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 break;
373 }
374 const CDCHit* nextcdcHit = nextcdcRecoHit->getCDCHit();
375 const int nextILayer = nextcdcHit->getILayer();
376 const int nextSuperlayer = nextcdcHit->getISuperLayer();
377 nextLayer = (nextSuperlayer == 0) ? nextILayer : (8 + (nextSuperlayer - 1) * 6 + nextILayer);
378 lastHitInCurrentLayer = (nextLayer != currentLayer);
379 }
380
381 // find the position of the endpoints of the sense wire
382 const ROOT::Math::XYZVector& wirePosF = cdcgeo.wireForwardPosition(wireID, CDCGeometryPar::c_Aligned);
383
384 int nWires = cdcgeo.nWiresInLayer(currentLayer);
385
386 // radii of field wires for this layer
387 double inner = cdcgeo.innerRadiusWireLayer()[currentLayer];
388 double outer = cdcgeo.outerRadiusWireLayer()[currentLayer];
389
390 double topHeight = outer - wirePosF.Rho();
391 double bottomHeight = wirePosF.Rho() - inner;
392 double cellHeight = topHeight + bottomHeight;
393 double topHalfWidth = M_PI * outer / nWires;
394 double bottomHalfWidth = M_PI * inner / nWires;
395 double cellHalfWidth = M_PI * wirePosF.Rho() / nWires;
396
397 // first construct the boundary lines, then create the cell
398 const DedxPoint tl = DedxPoint(-topHalfWidth, topHeight);
399 const DedxPoint tr = DedxPoint(topHalfWidth, topHeight);
400 const DedxPoint br = DedxPoint(bottomHalfWidth, -bottomHeight);
401 const DedxPoint bl = DedxPoint(-bottomHalfWidth, -bottomHeight);
402 DedxDriftCell c = DedxDriftCell(tl, tr, br, bl);
403
404 // make sure the MOP is reasonable (an exception is thrown for bad numerics)
405 try {
406 const genfit::MeasuredStateOnPlane& mop = fi->getFittedState();
407
408 // use the MOP to determine the DOCA and entrance angle
409 B2Vector3D fittedPoca = mop.getPos();
410 const TVector3& pocaMom = mop.getMom();
411 if (tp == gftrackPoints.begin() || cdcMom == 0) {
412 cdcMom = pocaMom.Mag();
413 dedxTrack->m_pCDC = cdcMom;
414 }
415 if (nomom)
416 dedxTrack->m_p = cdcMom;
417
418 // get the doca and entrance angle information.
419 // constructPlane places the coordinate center in the POCA to the
420 // wire. Using this is the default behavior. If this should be too
421 // slow, as it has to re-evaluate the POCA
422 // B2Vector3D pocaOnWire = cdcRecoHit->constructPlane(mop)->getO();
423
424 // uses the plane determined by the track fit.
425 B2Vector3D pocaOnWire = mop.getPlane()->getO(); // DOUBLE CHECK THIS --\/
426
427 // The vector from the wire to the track.
428 B2Vector3D B2WireDoca = fittedPoca - pocaOnWire;
429
430 // the sign of the doca is defined here to be positive in the +x dir in the cell
431 double doca = B2WireDoca.Perp();
432 double phidiff = fittedPoca.Phi() - pocaOnWire.Phi();
433 // be careful about "wrap around" cases when the poca and wire are close, but
434 // the difference in phi is largy
435 if (phidiff > -3.1416 && (phidiff < 0 || phidiff > 3.1416)) doca *= -1;
436
437 // The opening angle of the track momentum direction
438 const double px = pocaMom.X();
439 const double py = pocaMom.Y();
440 const double wx = pocaOnWire.X();
441 const double wy = pocaOnWire.Y();
442 const double cross = wx * py - wy * px;
443 const double dot = wx * px + wy * py;
444 double entAng = atan2(cross, dot);
445
446 // re-scaled (RS) doca and entAng variable: map to square cell
447 double cellR = 2 * cellHalfWidth / cellHeight;
448 double tana = 100.0;
449 if (std::abs(2 * atan(1) - std::abs(entAng)) < 0.01)tana = 100 * (entAng / std::abs(entAng)); //avoid infinity at pi/2
450 else tana = std::tan(entAng);
451 double docaRS = doca * std::sqrt((1 + cellR * cellR * tana * tana) / (1 + tana * tana));
452 double entAngRS = std::atan(tana / cellR);
453
455 int adcbaseCount = cdcHit->getADCCount(); // pedestal subtracted?
456 int adcCount = (m_DBNonlADC && m_usePrediction
457 && numMCParticles == 0) ? m_DBNonlADC->getCorrectedADC(adcbaseCount, currentLayer) : adcbaseCount;
458
459 double hitCharge = translator.getCharge(adcCount, wireID, false, pocaOnWire.Z(), pocaMom.Phi());
460 int driftT = cdcHit->getTDCCount();
461
462 // we want electrons to be one, so artificially scale the adcCount
463 double dadcCount = 1.0 * adcCount;
464 if (dedxTrack->m_scale != 0) dadcCount /= dedxTrack->m_scale;
465
466 RealisticTDCCountTranslator realistictdc;
467 double driftDRealistic = realistictdc.getDriftLength(driftT, wireID, 0, true, pocaOnWire.Z(), pocaMom.Phi(), pocaMom.Theta());
468 double driftDRealisticRes = realistictdc.getDriftLengthResolution(driftDRealistic, wireID, true, pocaOnWire.Z(), pocaMom.Phi(),
469 pocaMom.Theta());
470
471 // now calculate the path length for this hit
472 double celldx = c.dx(doca, entAng);
473 if (c.isValid()) {
474 // get the wire gain constant
475 double wiregain = (m_DBWireGains && m_usePrediction && numMCParticles == 0) ? m_DBWireGains->getWireGain(iwire) : 1.0;
476
477 //normalization of rescaled doca wrt cell size for layer dependent 2D corrections
478 double normDocaRS = docaRS / cellHalfWidth;
479 double twodcor = (m_DB2DCell && m_usePrediction
480 && numMCParticles == 0) ? m_DB2DCell->getMean(currentLayer, normDocaRS, entAngRS) : 1.0;
481
482 // get the 1D cleanup correction
483 double onedcor = (m_DB1DCell && m_usePrediction && numMCParticles == 0) ? m_DB1DCell->getMean(currentLayer, entAngRS) : 1.0;
484
485 // apply the calibration to dE to propagate to both hit and layer measurements
486 // Note: could move the sin(theta) here since it is common accross the track
487 // It is applied in two places below (hit level and layer level)
488 double correction = dedxTrack->m_runGain * dedxTrack->m_cosCor * dedxTrack->m_cosEdgeCor * dedxTrack->m_timeGain * wiregain *
489 twodcor * onedcor;
490
491 // --------------------
492 // save individual hits (even for dead wires)
493 // --------------------
494 if (correction != 0) dadcCount = dadcCount / correction;
495 else dadcCount = 0;
496
497 double cellDedx = (dadcCount / celldx);
498
499 // correct for path length through the cell
500 if (nomom) cellDedx *= std::sin(std::atan(1 / fitResult->getCotTheta()));
501 else cellDedx *= std::sin(trackMom.Theta());
502
504 dedxTrack->addHit(wire, iwire, currentLayer, doca, docaRS, entAng, entAngRS,
505 adcCount, adcbaseCount, hitCharge, celldx, cellDedx, cellHeight, cellHalfWidth, driftT,
506 driftDRealistic, driftDRealisticRes, wiregain, twodcor, onedcor,
507 foundByTrackFinder, weightPionHypo, weightKaonHypo, weightProtHypo);
508
509 // --------------------
510 // save layer hits only with active wires
511 // --------------------
512 if (correction != 0) {
513
514 layerdE += dadcCount;
515 layerdx += celldx;
516
517 if (celldx > longesthit) {
518 longesthit = celldx;
519 wirelongesthit = iwire;
520 }
521 nhitscombined++;
522 }
523 }
524 } catch (genfit::Exception&) {
525 B2WARNING("Track: " << mtrack << ": genfit::MeasuredStateOnPlane exception...");
526 continue;
527 }
528
529 // check if there are any more hits in this layer
530 if (lastHitInCurrentLayer) {
531 if (layerdx > 0) {
532 double totalDistance;
533 if (nomom) totalDistance = layerdx / std::sin(std::atan(1 / fitResult->getCotTheta()));
534 else totalDistance = layerdx / std::sin(trackMom.Theta());
535 double layerDedx = layerdE / totalDistance;
536
537 // save the information for this layer
538 if (layerDedx > 0) {
539 dedxTrack->addDedx(nhitscombined, wirelongesthit, currentLayer, totalDistance, layerDedx);
540 // save the PID information if using individual hits
542 // use the momentum valid in the cdc
543 saveLookupLogl(dedxTrack->m_cdcLogl, dedxTrack->m_pCDC, layerDedx);
544 }
545 }
546 }
547 // stop when the track starts to curl
548 if (!m_backHalfCurlers && nextLayer < currentLayer) break;
549
550 layerdE = 0;
551 layerdx = 0;
552 nhitscombined = 0;
553 wirelongesthit = 0;
554 longesthit = 0;
555 }
556 } // end of loop over CDC hits for this track
557
558 // Determine the number of hits to be used
559 //m_lDedx is a ector for layerDedx and created w/ ->adddedx method above
560 if (dedxTrack->m_lDedx.empty()) {
561 B2DEBUG(29, "Found track with no hits, ignoring.");
562 continue;
563 } else {
564 // determine the number of hits for this track (used below)
565 const int numDedx = dedxTrack->m_lDedx.size();
566 // add a factor of 0.51 here to make sure we are rounding appropriately...
567 const int lowEdgeTrunc = int(numDedx * m_removeLowest + 0.51);
568 const int highEdgeTrunc = int(numDedx * (1 - m_removeHighest) + 0.51);
569 dedxTrack->m_lNHitsUsed = highEdgeTrunc - lowEdgeTrunc;
570 }
571
572 // Get the truncated mean
573 //
574 // If using track-level MC, get the predicted mean and resolution and throw a random
575 // number to get the simulated dE/dx truncated mean. Otherwise, calculate the truncated
576 // mean from the simulated hits (hit-level MC).
578 calculateMeans(&(dedxTrack->m_dedxAvg),
579 &(dedxTrack->m_dedxAvgTruncatedNoSat),
580 &(dedxTrack->m_dedxAvgTruncatedErr),
581 dedxTrack->m_lDedx);
582
583 // apply the "hadron correction" only to data
584 if (numMCParticles == 0)
585 dedxTrack->m_dedxAvgTruncated = D2I(costh, I2D(costh, 1.00) / 1.00 * dedxTrack->m_dedxAvgTruncatedNoSat);
586 else dedxTrack->m_dedxAvgTruncated = dedxTrack->m_dedxAvgTruncatedNoSat;
587 }
588
589 // If this is a MC track, get the track-level dE/dx
590 if (numMCParticles != 0 && dedxTrack->m_mcmass > 0 && dedxTrack->m_pTrue != 0) {
591 // determine the predicted mean and resolution
592 double mean = getMean(dedxTrack->m_pCDC / dedxTrack->m_mcmass);
593 double sigma = getSigma(mean, dedxTrack->m_lNHitsUsed,
594 dedxTrack->m_cosTheta, dedxTrack->m_timeReso);
595 dedxTrack->m_simDedx = gRandom->Gaus(mean, sigma);
596 while (dedxTrack->m_simDedx < 0)
597 dedxTrack->m_simDedx = gRandom->Gaus(mean, sigma);
598 if (m_trackLevel)
599 dedxTrack->m_dedxAvgTruncated = dedxTrack->m_simDedx;
600 }
601
602 // save the PID information for both lookup tables and parameterized means and resolutions
603 saveChiValue(dedxTrack->m_cdcChi, dedxTrack->m_predmean, dedxTrack->m_predres, dedxTrack->m_pCDC, dedxTrack->m_dedxAvgTruncated,
604 dedxTrack->m_cosTheta, dedxTrack->m_lNHitsUsed, dedxTrack->m_timeReso);
606 saveLookupLogl(dedxTrack->m_cdcLogl, dedxTrack->m_pCDC, dedxTrack->m_dedxAvgTruncated);
607
608 // save CDCDedxLikelihood
609 // use parameterized method if called or if pdf file for lookup tables are empty
610 double pidvalues[Const::ChargedStable::c_SetSize];
612 if (m_usePrediction) {
613 for (const Const::ChargedStable pdgIter : set) {
614 pidvalues[pdgIter.getIndex()] = -0.5 * dedxTrack->m_cdcChi[pdgIter.getIndex()] * dedxTrack->m_cdcChi[pdgIter.getIndex()];
615 }
616 } else {
617 for (const Const::ChargedStable pdgIter : set) {
618 pidvalues[pdgIter.getIndex()] = dedxTrack->m_cdcLogl[pdgIter.getIndex()];
619 }
620 }
621
622 CDCDedxLikelihood* likelihoodObj = m_dedxLikelihoods.appendNew(pidvalues);
623 track.addRelationTo(likelihoodObj);
624
626 // book the information for this track
627 CDCDedxTrack* newCDCDedxTrack = m_dedxTracks.appendNew(*dedxTrack);
628 track.addRelationTo(newCDCDedxTrack);
629 }
630
631 } // end of loop over tracks
632}
633
635{
636
637 B2DEBUG(29, "CDCDedxPIDModule exiting");
638}
639
640void CDCDedxPIDModule::calculateMeans(double* mean, double* truncatedMean, double* truncatedMeanErr,
641 const std::vector<double>& dedx) const
642{
643 // Calculate the truncated average by skipping the lowest & highest
644 // events in the array of dE/dx values
645 std::vector<double> sortedDedx = dedx;
646 std::sort(sortedDedx.begin(), sortedDedx.end());
647 sortedDedx.erase(std::remove(sortedDedx.begin(), sortedDedx.end(), 0), sortedDedx.end());
648 sortedDedx.shrink_to_fit();
649
650 double truncatedMeanTmp = 0.0;
651 double meanTmp = 0.0;
652 double sumOfSquares = 0.0;
653 int numValuesTrunc = 0;
654 const int numDedx = sortedDedx.size();
655
656 // add a factor of 0.51 here to make sure we are rounding appropriately...
657 const int lowEdgeTrunc = int(numDedx * m_removeLowest + 0.51);
658 const int highEdgeTrunc = int(numDedx * (1 - m_removeHighest) + 0.51);
659 for (int i = 0; i < numDedx; i++) {
660 meanTmp += sortedDedx[i];
661 if (i >= lowEdgeTrunc and i < highEdgeTrunc) {
662 truncatedMeanTmp += sortedDedx[i];
663 sumOfSquares += sortedDedx[i] * sortedDedx[i];
664 numValuesTrunc++;
665 }
666 }
667
668 if (numDedx != 0) {
669 meanTmp /= numDedx;
670 }
671 if (numValuesTrunc != 0) {
672 truncatedMeanTmp /= numValuesTrunc;
673 } else {
674 truncatedMeanTmp = meanTmp;
675 }
676
677 *mean = meanTmp;
678 *truncatedMean = truncatedMeanTmp;
679
680 if (numValuesTrunc > 1) {
681 *truncatedMeanErr = sqrt(sumOfSquares / double(numValuesTrunc) - truncatedMeanTmp * truncatedMeanTmp) / double(
682 numValuesTrunc - 1);
683 } else {
684 *truncatedMeanErr = 0;
685 }
686}
687
688void CDCDedxPIDModule::saveLookupLogl(double(&logl)[Const::ChargedStable::c_SetSize], double p, double dedx)
689{
690 //all pdfs have the same dimensions
691 const TH2F* pdf = m_DBDedxPDFs->getCDCPDF(0, !m_useIndividualHits);
692 const Int_t binX = pdf->GetXaxis()->FindFixBin(p);
693 const Int_t binY = pdf->GetYaxis()->FindFixBin(dedx);
694
695 for (unsigned int iPart = 0; iPart < Const::ChargedStable::c_SetSize; iPart++) {
696 pdf = m_DBDedxPDFs->getCDCPDF(iPart, !m_useIndividualHits);
697 if (pdf->GetEntries() == 0) { //might be NULL if m_ignoreMissingParticles is set
698 B2WARNING("NO CDC PDFS...");
699 continue;
700 }
701 double probability = 0.0;
702
703 //check if this is still in the histogram, take overflow bin otherwise
704 if (binX < 1 or binX > pdf->GetNbinsX()
705 or binY < 1 or binY > pdf->GetNbinsY()) {
706 probability = pdf->GetBinContent(binX, binY);
707 } else {
708 //in normal histogram range. Of course ROOT has a bug that Interpolate()
709 //is not declared as const but it does not modify the internal state so
710 //fine, const_cast it is.
711 probability = const_cast<TH2F*>(pdf)->Interpolate(p, dedx);
712 }
713
714 if (probability != probability)
715 B2ERROR("probability NAN for a track with p=" << p << " and dedx=" << dedx);
716
717 //my pdfs aren't perfect...
718 if (probability == 0.0)
719 probability = m_useIndividualHits ? (1e-5) : (1e-3); //likelihoods for truncated mean are much higher
720 logl[iPart] += log(probability);
721 }
722}
723
724double CDCDedxPIDModule::D2I(const double cosTheta, const double D) const
725{
726 double absCosTheta = fabs(cosTheta);
727 double projection = pow(absCosTheta, m_hadronpars[3]) + m_hadronpars[2];
728 if (projection == 0) {
729 B2WARNING("Something wrong with dE/dx hadron constants!");
730 return D;
731 }
732
733 double chargeDensity = D / projection;
734 double numerator = 1 + m_hadronpars[0] * chargeDensity;
735 double denominator = 1 + m_hadronpars[1] * chargeDensity;
736
737 if (denominator == 0) {
738 B2WARNING("Something wrong with dE/dx hadron constants!");
739 return D;
740 }
741
742 double I = D * m_hadronpars[4] * numerator / denominator;
743 return I;
744}
745
746double CDCDedxPIDModule::I2D(const double cosTheta, const double I) const
747{
748 double absCosTheta = fabs(cosTheta);
749 double projection = pow(absCosTheta, m_hadronpars[3]) + m_hadronpars[2];
750
751 if (projection == 0 || m_hadronpars[4] == 0) {
752 B2WARNING("Something wrong with dE/dx hadron constants!");
753 return I;
754 }
755
756 double a = m_hadronpars[0] / projection;
757 double b = 1 - m_hadronpars[1] / projection * (I / m_hadronpars[4]);
758 double c = -1.0 * I / m_hadronpars[4];
759
760 if (b == 0 && a == 0) {
761 B2WARNING("both a and b coefficiants for hadron correction are 0");
762 return I;
763 }
764
765 double discr = b * b - 4.0 * a * c;
766 if (discr < 0) {
767 B2WARNING("negative discriminant; return uncorrectecd value");
768 return I;
769 }
770
771 double D = (a != 0) ? (-b + sqrt(discr)) / (2.0 * a) : -c / b;
772 if (D < 0) {
773 B2WARNING("D is less 0! will try another solution");
774 D = (a != 0) ? (-b - sqrt(discr)) / (2.0 * a) : -c / b;
775 if (D < 0) {
776 B2WARNING("D is still less 0! just return uncorrectecd value");
777 return I;
778 }
779 }
780
781 return D;
782}
783
784double CDCDedxPIDModule::meanCurve(double* x, double* par, int version) const
785{
786 // calculate the predicted mean value as a function of beta-gamma (bg)
787 // this is done with a different function depending on the value of bg
788 double f = 0;
789
790 if (version == 0) {
791 if (par[0] == 1)
792 f = par[1] * std::pow(std::sqrt(x[0] * x[0] + 1), par[3]) / std::pow(x[0], par[3]) *
793 (par[2] - par[5] * std::log(1 / x[0])) - par[4] + std::exp(par[6] + par[7] * x[0]);
794 else if (par[0] == 2)
795 f = par[1] * std::pow(x[0], 3) + par[2] * x[0] * x[0] + par[3] * x[0] + par[4];
796 else if (par[0] == 3)
797 f = -1.0 * par[1] * std::log(par[4] + std::pow(1 / x[0], par[2])) + par[3];
798 }
799
800 return f;
801}
802
803double CDCDedxPIDModule::getMean(double bg) const
804{
805 // define the section of the mean to use
806 double A = 0, B = 0, C = 0;
807 if (bg < 4.5)
808 A = 1;
809 else if (bg < 10)
810 B = 1;
811 else
812 C = 1;
813
814 double x[1]; x[0] = bg;
815 double parsA[9];
816 double parsB[5];
817 double parsC[5];
818
819 parsA[0] = 1; parsB[0] = 2; parsC[0] = 3;
820 for (int i = 0; i < 15; ++i) {
821 if (i < 7) parsA[i + 1] = m_meanpars[i];
822 else if (i < 11) parsB[i % 7 + 1] = m_meanpars[i];
823 else parsC[i % 11 + 1] = m_meanpars[i];
824 }
825
826 // calculate dE/dx from the Bethe-Bloch mean
827 double partA = meanCurve(x, parsA, 0);
828 double partB = meanCurve(x, parsB, 0);
829 double partC = meanCurve(x, parsC, 0);
830
831 return (A * partA + B * partB + C * partC);
832}
833
834double CDCDedxPIDModule::sigmaCurve(double* x, const double* par, int version) const
835{
836 // calculate the predicted mean value as a function of beta-gamma (bg)
837 // this is done with a different function depending dE/dx, nhit, and sin(theta)
838 double f = 0;
839
840 if (version == 0) {
841 if (par[0] == 1) { // return dedx parameterization
842 f = par[1] + par[2] * x[0];
843 } else if (par[0] == 2) { // return nhit or sin(theta) parameterization
844 f = par[1] * std::pow(x[0], 4) + par[2] * std::pow(x[0], 3) +
845 par[3] * x[0] * x[0] + par[4] * x[0] + par[5];
846 } else if (par[0] == 3) { // return cos(theta) parameterization
847 f = par[1] * exp(-0.5 * pow(((x[0] - par[2]) / par[3]), 2)) +
848 par[4] * pow(x[0], 6) + par[5] * pow(x[0], 5) + par[6] * pow(x[0], 4) +
849 par[7] * pow(x[0], 3) + par[8] * x[0] * x[0] + par[9] * x[0] + par[10];
850 }
851 }
852
853 return f;
854}
855
856
857double CDCDedxPIDModule::getSigma(double dedx, double nhit, double cos, double timereso) const
858{
859
860 double x[1];
861 double dedxpar[3];
862 double nhitpar[6];
863 double cospar[11];
864
865 dedxpar[0] = 1; nhitpar[0] = 2; cospar[0] = 3;
866 for (int i = 0; i < 10; ++i) {
867 if (i < 2) dedxpar[i + 1] = m_sigmapars[i];
868 if (i < 5) nhitpar[i + 1] = m_sigmapars[i + 2];
869 cospar[i + 1] = m_sigmapars[i + 7];
870 }
871
872 // determine sigma from the parameterization
873 x[0] = dedx;
874 double corDedx = sigmaCurve(x, dedxpar, 0);
875
876 x[0] = nhit;
877 double corNHit;
878 int nhit_min = 8, nhit_max = 37;
879
880 if (nhit < nhit_min) {
881 x[0] = nhit_min;
882 corNHit = sigmaCurve(x, nhitpar, 0) * sqrt(nhit_min / nhit);
883 } else if (nhit > nhit_max) {
884 x[0] = nhit_max;
885 corNHit = sigmaCurve(x, nhitpar, 0) * sqrt(nhit_max / nhit);
886 } else corNHit = sigmaCurve(x, nhitpar, 0);
887
888 x[0] = cos;
889 double corCos = sigmaCurve(x, cospar, 0);
890
891 return (corDedx * corCos * corNHit * timereso);
892}
893
895 double(&predmean)[Const::ChargedStable::c_SetSize], double(&predsigma)[Const::ChargedStable::c_SetSize], double p, double dedx,
896 double cos, int nhit, double timereso) const
897{
898 // determine a chi value for each particle type
900 for (const Const::ChargedStable pdgIter : set) {
901 double bg = p / pdgIter.getMass();
902
903 // determine the predicted mean and resolution
904 double mean = getMean(bg);
905 double sigma = getSigma(mean, nhit, cos, timereso);
906
907 predmean[pdgIter.getIndex()] = mean;
908 predsigma[pdgIter.getIndex()] = sigma;
909
910 // fill the chi value for this particle type
911 if (sigma != 0) chi[pdgIter.getIndex()] = ((dedx - mean) / (sigma));
912 }
913}
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 Mag() const
The magnitude (rho in spherical coordinate system).
Definition: B2Vector3.h:159
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-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.
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.
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
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
const ParticleType & at(unsigned int index) const
Return particle at given index, or end() if out of range.
Definition: Const.h:549
int getPDGCode() const
PDG code.
Definition: Const.h:473
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: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 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
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.
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:560
#define REG_MODULE(moduleName)
Register the given module (without 'Module' suffix) with the framework.
Definition: Module.h:650
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
Definition: beamHelpers.h:163
MCParticle * getMother() const
Returns a pointer to the mother particle.
Definition: MCParticle.h:600
Abstract base class for different kinds of events.