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