CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
MuonTrackAnalyzer.cc
Go to the documentation of this file.
1 
8 
9 // Collaborating Class Header
15 
17 
21 
23 
25 
29 
32 
33 #include "TFile.h"
34 #include "TH1F.h"
35 #include "TH2F.h"
36 
37 using namespace std;
38 using namespace edm;
39 
42  // service parameters
43  pset = ps;
44  ParameterSet serviceParameters = pset.getParameter<ParameterSet>("ServiceParameters");
45  // the services
46  theService = new MuonServiceProxy(serviceParameters, consumesCollector());
47 
48  theSimTracksLabel = edm::InputTag("g4SimHits");
49  theSimTracksToken = consumes<edm::SimTrackContainer>(theSimTracksLabel);
50 
51  theTracksLabel = pset.getParameter<InputTag>("Tracks");
52  theTracksToken = consumes<reco::TrackCollection>(theTracksLabel);
53  doTracksAnalysis = pset.getUntrackedParameter<bool>("DoTracksAnalysis", true);
54 
55  doSeedsAnalysis = pset.getUntrackedParameter<bool>("DoSeedsAnalysis", false);
56  if (doSeedsAnalysis) {
57  theSeedsLabel = pset.getParameter<InputTag>("MuonSeed");
58  theSeedsToken = consumes<TrajectorySeedCollection>(theSeedsLabel);
59  ParameterSet updatorPar = pset.getParameter<ParameterSet>("MuonUpdatorAtVertexParameters");
60  theSeedPropagatorName = updatorPar.getParameter<string>("Propagator");
61 
62  theUpdator = new MuonUpdatorAtVertex(updatorPar, theService);
63  }
64 
65  theCSCSimHitLabel = pset.getParameter<InputTag>("CSCSimHit");
66  theDTSimHitLabel = pset.getParameter<InputTag>("DTSimHit");
67  theRPCSimHitLabel = pset.getParameter<InputTag>("RPCSimHit");
68  theCSCSimHitToken = consumes<std::vector<PSimHit> >(theCSCSimHitLabel);
69  theDTSimHitToken = consumes<std::vector<PSimHit> >(theDTSimHitLabel);
70  theRPCSimHitToken = consumes<std::vector<PSimHit> >(theRPCSimHitLabel);
71 
72  theEtaRange = (EtaRange)pset.getParameter<int>("EtaRange");
73 
74  // number of sim tracks
75  numberOfSimTracks = 0;
76  // number of reco tracks
77  numberOfRecTracks = 0;
78 
80  out = pset.getUntrackedParameter<string>("rootFileName");
81  dirName_ = pset.getUntrackedParameter<std::string>("dirName");
82  subsystemname_ = pset.getUntrackedParameter<std::string>("subSystemFolder", "YourSubsystem");
83 }
84 
87  if (theService)
88  delete theService;
89 }
90 
92  edm::Run const &iRun,
93  edm::EventSetup const & /* iSetup */) {
94  ibooker.cd();
95 
96  InputTag algo = theTracksLabel;
97  string dirName = dirName_;
98  if (!algo.process().empty())
99  dirName += algo.process() + "_";
100  if (!algo.label().empty())
101  dirName += algo.label() + "_";
102  if (!algo.instance().empty())
103  dirName += algo.instance() + "";
104  if (dirName.find("Tracks") < dirName.length()) {
105  dirName.replace(dirName.find("Tracks"), 6, "");
106  }
107  std::replace(dirName.begin(), dirName.end(), ':', '_');
108  ibooker.setCurrentFolder(dirName);
109 
110  //ibooker.goUp();
111  std::string simName = dirName;
112  simName += "/SimTracks";
113  hSimTracks = new HTrackVariables(ibooker, simName, "SimTracks");
114 
115  ibooker.cd();
116  ibooker.setCurrentFolder(dirName);
117 
118  // Create the root file
119  //theFile = new TFile(theRootFileName.c_str(), "RECREATE");
120 
121  if (doSeedsAnalysis) {
122  ibooker.cd();
123  ibooker.setCurrentFolder(dirName);
124  hRecoSeedInner = new HTrack(ibooker, dirName, "RecoSeed", "Inner");
125  hRecoSeedPCA = new HTrack(ibooker, dirName, "RecoSeed", "PCA");
126  }
127 
128  if (doTracksAnalysis) {
129  ibooker.cd();
130  ibooker.setCurrentFolder(dirName);
131  hRecoTracksPCA = new HTrack(ibooker, dirName, "RecoTracks", "PCA");
132  hRecoTracksInner = new HTrack(ibooker, dirName, "RecoTracks", "Inner");
133  hRecoTracksOuter = new HTrack(ibooker, dirName, "RecoTracks", "Outer");
134 
135  ibooker.cd();
136  ibooker.setCurrentFolder(dirName);
137 
138  // General Histos
139 
140  hChi2 = ibooker.book1D("chi2", "#chi^2", 200, 0, 200);
141  hChi2VsEta = ibooker.book2D("chi2VsEta", "#chi^2 VS #eta", 120, -3., 3., 200, 0, 200);
142 
143  hChi2Norm = ibooker.book1D("chi2Norm", "Normalized #chi^2", 400, 0, 100);
144  hChi2NormVsEta = ibooker.book2D("chi2NormVsEta", "Normalized #chi^2 VS #eta", 120, -3., 3., 400, 0, 100);
145 
146  hHitsPerTrack = ibooker.book1D("HitsPerTrack", "Number of hits per track", 55, 0, 55);
147  hHitsPerTrackVsEta =
148  ibooker.book2D("HitsPerTrackVsEta", "Number of hits per track VS #eta", 120, -3., 3., 55, 0, 55);
149 
150  hDof = ibooker.book1D("dof", "Number of Degree of Freedom", 55, 0, 55);
151  hDofVsEta = ibooker.book2D("dofVsEta", "Number of Degree of Freedom VS #eta", 120, -3., 3., 55, 0, 55);
152 
153  hChi2Prob = ibooker.book1D("chi2Prob", "#chi^2 probability", 200, 0, 1);
154  hChi2ProbVsEta = ibooker.book2D("chi2ProbVsEta", "#chi^2 probability VS #eta", 120, -3., 3., 200, 0, 1);
155 
156  hNumberOfTracks = ibooker.book1D("NumberOfTracks", "Number of reconstructed tracks per event", 200, 0, 200);
157  hNumberOfTracksVsEta = ibooker.book2D(
158  "NumberOfTracksVsEta", "Number of reconstructed tracks per event VS #eta", 120, -3., 3., 10, 0, 10);
159 
160  hChargeVsEta = ibooker.book2D("ChargeVsEta", "Charge vs #eta gen", 120, -3., 3., 4, -2., 2.);
161  hChargeVsPt = ibooker.book2D("ChargeVsPt", "Charge vs P_{T} gen", 250, 0, 200, 4, -2., 2.);
162  hPtRecVsPtGen = ibooker.book2D("PtRecVsPtGen", "P_{T} rec vs P_{T} gen", 250, 0, 200, 250, 0, 200);
163 
164  hDeltaPtVsEta = ibooker.book2D("DeltaPtVsEta", "#Delta P_{t} vs #eta gen", 120, -3., 3., 500, -250., 250.);
165  hDeltaPt_In_Out_VsEta =
166  ibooker.book2D("DeltaPt_In_Out_VsEta_", "P^{in}_{t} - P^{out}_{t} vs #eta gen", 120, -3., 3., 500, -250., 250.);
167  }
168 }
169 
170 void MuonTrackAnalyzer::analyze(const Event &event, const EventSetup &eventSetup) {
171  LogDebug("MuonTrackAnalyzer") << "Run: " << event.id().run() << " Event: " << event.id().event();
172 
173  // Update the services
174  theService->update(eventSetup);
175 
176  Handle<SimTrackContainer> simTracks;
177  event.getByToken(theSimTracksToken, simTracks);
178  fillPlots(event, simTracks);
179 
180  if (doTracksAnalysis)
181  tracksAnalysis(event, eventSetup, simTracks);
182 
183  if (doSeedsAnalysis)
184  seedsAnalysis(event, eventSetup, simTracks);
185 }
186 
188  const EventSetup &eventSetup,
189  Handle<SimTrackContainer> simTracks) {
191 
192  // Get the RecTrack collection from the event
194  event.getByToken(theSeedsToken, seeds);
195 
196  LogTrace("MuonTrackAnalyzer") << "Number of reconstructed seeds: " << seeds->size() << endl;
197 
198  for (TrajectorySeedCollection::const_iterator seed = seeds->begin(); seed != seeds->end(); ++seed) {
199  TrajectoryStateOnSurface seedTSOS = getSeedTSOS(*seed);
200  pair<SimTrack, double> sim = getSimTrack(seedTSOS, simTracks);
201  fillPlots(seedTSOS, sim.first, hRecoSeedInner, debug);
202 
203  std::pair<bool, FreeTrajectoryState> propSeed = theUpdator->propagateToNominalLine(seedTSOS);
204  if (propSeed.first)
205  fillPlots(propSeed.second, sim.first, hRecoSeedPCA, debug);
206  else
207  LogTrace("MuonTrackAnalyzer") << "Error in seed propagation" << endl;
208  }
209 }
210 
212  const EventSetup &eventSetup,
213  Handle<SimTrackContainer> simTracks) {
215 
216  // Get the RecTrack collection from the event
218  event.getByToken(theTracksToken, tracks);
219 
220  LogTrace("MuonTrackAnalyzer") << "Reconstructed tracks: " << tracks->size() << endl;
221  hNumberOfTracks->Fill(tracks->size());
222 
223  if (!tracks->empty())
224  numberOfRecTracks++;
225 
226  // Loop over the Rec tracks
227  for (reco::TrackCollection::const_iterator t = tracks->begin(); t != tracks->end(); ++t) {
228  reco::TransientTrack track(*t, &*theService->magneticField(), theService->trackingGeometry());
229 
230  TrajectoryStateOnSurface outerTSOS = track.outermostMeasurementState();
231  TrajectoryStateOnSurface innerTSOS = track.innermostMeasurementState();
232  TrajectoryStateOnSurface pcaTSOS = track.impactPointState();
233 
234  pair<SimTrack, double> sim = getSimTrack(pcaTSOS, simTracks);
235  SimTrack simTrack = sim.first;
236  hNumberOfTracksVsEta->Fill(simTrack.momentum().eta(), tracks->size());
237  fillPlots(track, simTrack);
238 
239  LogTrace("MuonTrackAnalyzer") << "State at the outer surface: " << endl;
240  fillPlots(outerTSOS, simTrack, hRecoTracksOuter, debug);
241 
242  LogTrace("MuonTrackAnalyzer") << "State at the inner surface: " << endl;
243  fillPlots(innerTSOS, simTrack, hRecoTracksInner, debug);
244 
245  LogTrace("MuonTrackAnalyzer") << "State at PCA: " << endl;
246  fillPlots(pcaTSOS, simTrack, hRecoTracksPCA, debug);
247 
248  double deltaPt_in_out = innerTSOS.globalMomentum().perp() - outerTSOS.globalMomentum().perp();
249  hDeltaPt_In_Out_VsEta->Fill(simTrack.momentum().eta(), deltaPt_in_out);
250 
251  double deltaPt_pca_sim = pcaTSOS.globalMomentum().perp() - sqrt(simTrack.momentum().Perp2());
252  hDeltaPtVsEta->Fill(simTrack.momentum().eta(), deltaPt_pca_sim);
253 
254  hChargeVsEta->Fill(simTrack.momentum().eta(), pcaTSOS.charge());
255 
256  hChargeVsPt->Fill(sqrt(simTrack.momentum().perp2()), pcaTSOS.charge());
257 
258  hPtRecVsPtGen->Fill(sqrt(simTrack.momentum().perp2()), pcaTSOS.globalMomentum().perp());
259  }
260  LogTrace("MuonTrackAnalyzer") << "--------------------------------------------" << endl;
261 }
262 
264  if (!checkMuonSimHitPresence(event, simTracks))
265  return;
266 
267  // Loop over the Sim tracks
268  SimTrackContainer::const_iterator simTrack;
269  LogTrace("MuonTrackAnalyzer") << "Simulated tracks: " << simTracks->size() << endl;
270 
271  for (simTrack = simTracks->begin(); simTrack != simTracks->end(); ++simTrack)
272  if (abs((*simTrack).type()) == 13) {
273  if (!isInTheAcceptance((*simTrack).momentum().eta()))
274  continue; // FIXME!!
275 
276  numberOfSimTracks++;
277 
278  LogTrace("MuonTrackAnalyzer") << "Simualted muon:" << endl;
279  LogTrace("MuonTrackAnalyzer") << "Sim pT: " << sqrt((*simTrack).momentum().perp2()) << endl;
280  LogTrace("MuonTrackAnalyzer") << "Sim Eta: " << (*simTrack).momentum().eta() << endl; // FIXME
281 
282  hSimTracks->Fill((*simTrack).momentum().mag(),
283  sqrt((*simTrack).momentum().perp2()),
284  (*simTrack).momentum().eta(),
285  (*simTrack).momentum().phi(),
286  -(*simTrack).type() / abs((*simTrack).type())); // Double FIXME
287  LogTrace("MuonTrackAnalyzer") << "hSimTracks filled" << endl;
288  }
289 
290  LogTrace("MuonTrackAnalyzer") << endl;
291 }
292 
294  LogTrace("MuonTrackAnalyzer") << "Analizer: New track, chi2: " << track.chi2() << " dof: " << track.ndof() << endl;
295  hChi2->Fill(track.chi2());
296  hDof->Fill(track.ndof());
297  hChi2Norm->Fill(track.normalizedChi2());
298  hHitsPerTrack->Fill(track.recHitsSize());
299 
300  hChi2Prob->Fill(ChiSquaredProbability(track.chi2(), track.ndof()));
301 
302  hChi2VsEta->Fill(simTrack.momentum().eta(), track.chi2());
303  hChi2NormVsEta->Fill(simTrack.momentum().eta(), track.normalizedChi2());
304  hChi2ProbVsEta->Fill(simTrack.momentum().eta(), ChiSquaredProbability(track.chi2(), track.ndof()));
305  hHitsPerTrackVsEta->Fill(simTrack.momentum().eta(), track.recHitsSize());
306  hDofVsEta->Fill(simTrack.momentum().eta(), track.ndof());
307 }
308 
311  HTrack *histo,
313  LogTrace("MuonTrackAnalyzer") << debug.dumpTSOS(recoTSOS) << endl;
314  histo->Fill(recoTSOS);
315 
316  GlobalVector tsosVect = recoTSOS.globalMomentum();
317  math::XYZVectorD reco(tsosVect.x(), tsosVect.y(), tsosVect.z());
318  double deltaRVal = deltaR<double>(reco.eta(), reco.phi(), simTrack.momentum().eta(), simTrack.momentum().phi());
319  histo->FillDeltaR(deltaRVal);
320 
321  histo->computeResolutionAndPull(recoTSOS, simTrack);
322 }
323 
326  HTrack *histo,
328  LogTrace("MuonTrackAnalyzer") << debug.dumpFTS(recoFTS) << endl;
329  histo->Fill(recoFTS);
330 
331  GlobalVector ftsVect = recoFTS.momentum();
332  math::XYZVectorD reco(ftsVect.x(), ftsVect.y(), ftsVect.z());
333  double deltaRVal = deltaR<double>(reco.eta(), reco.phi(), simTrack.momentum().eta(), simTrack.momentum().phi());
334  histo->FillDeltaR(deltaRVal);
335 
336  histo->computeResolutionAndPull(recoFTS, simTrack);
337 }
338 
340  Handle<SimTrackContainer> simTracks) {
341  // // Loop over the Sim tracks
342  // SimTrackContainer::const_iterator simTrack;
343 
344  // SimTrack result;
345  // int mu=0;
346  // for (simTrack = simTracks->begin(); simTrack != simTracks->end(); ++simTrack)
347  // if (abs((*simTrack).type()) == 13) {
348  // result = *simTrack;
349  // ++mu;
350  // }
351 
352  // if(mu != 1) LogTrace("MuonTrackAnalyzer") << "WARNING!! more than 1 simulated muon!!" <<endl;
353  // return result;
354 
355  // Loop over the Sim tracks
356  SimTrackContainer::const_iterator simTrack;
357 
359 
360  double bestDeltaR = 10e5;
361  for (simTrack = simTracks->begin(); simTrack != simTracks->end(); ++simTrack) {
362  if (abs((*simTrack).type()) != 13)
363  continue;
364 
365  // double newDeltaR = tsos.globalMomentum().basicVector().deltaR(simTrack->momentum().vect());
366  GlobalVector tsosVect = tsos.globalMomentum();
367  math::XYZVectorD vect(tsosVect.x(), tsosVect.y(), tsosVect.z());
368  double newDeltaR = deltaR<double>(vect.eta(), vect.phi(), simTrack->momentum().eta(), simTrack->momentum().phi());
369 
370  if (newDeltaR < bestDeltaR) {
371  LogTrace("MuonTrackAnalyzer") << "Matching Track with DeltaR = " << newDeltaR << endl;
372  bestDeltaR = newDeltaR;
373  result = *simTrack;
374  }
375  }
376  return pair<SimTrack, double>(result, bestDeltaR);
377 }
378 
380  switch (theEtaRange) {
381  case all:
382  return (abs(eta) <= 2.4) ? true : false;
383  case barrel:
384  return (abs(eta) < 1.1) ? true : false;
385  case endcap:
386  return (abs(eta) >= 1.1 && abs(eta) <= 2.4) ? true : false;
387  default: {
388  LogTrace("MuonTrackAnalyzer") << "No correct Eta range selected!! " << endl;
389  return false;
390  }
391  }
392 }
393 
395  // Get the SimHit collection from the event
396  Handle<PSimHitContainer> dtSimHits;
397  event.getByToken(theDTSimHitToken, dtSimHits);
398 
399  Handle<PSimHitContainer> cscSimHits;
400  event.getByToken(theCSCSimHitToken, cscSimHits);
401 
402  Handle<PSimHitContainer> rpcSimHits;
403  event.getByToken(theRPCSimHitToken, rpcSimHits);
404 
405  map<unsigned int, vector<const PSimHit *> > mapOfMuonSimHits;
406 
407  for (PSimHitContainer::const_iterator simhit = dtSimHits->begin(); simhit != dtSimHits->end(); ++simhit) {
408  if (abs(simhit->particleType()) != 13)
409  continue;
410  mapOfMuonSimHits[simhit->trackId()].push_back(&*simhit);
411  }
412 
413  for (PSimHitContainer::const_iterator simhit = cscSimHits->begin(); simhit != cscSimHits->end(); ++simhit) {
414  if (abs(simhit->particleType()) != 13)
415  continue;
416  mapOfMuonSimHits[simhit->trackId()].push_back(&*simhit);
417  }
418 
419  for (PSimHitContainer::const_iterator simhit = rpcSimHits->begin(); simhit != rpcSimHits->end(); ++simhit) {
420  if (abs(simhit->particleType()) != 13)
421  continue;
422  mapOfMuonSimHits[simhit->trackId()].push_back(&*simhit);
423  }
424 
425  bool presence = false;
426 
427  for (SimTrackContainer::const_iterator simTrack = simTracks->begin(); simTrack != simTracks->end(); ++simTrack) {
428  if (abs(simTrack->type()) != 13)
429  continue;
430 
431  map<unsigned int, vector<const PSimHit *> >::const_iterator mapIterator =
432  mapOfMuonSimHits.find(simTrack->trackId());
433 
434  if (mapIterator != mapOfMuonSimHits.end())
435  presence = true;
436  }
437 
438  return presence;
439 }
440 
442  // Get the Trajectory State on Det (persistent version of a TSOS) from the seed
443  PTrajectoryStateOnDet pTSOD = seed.startingState();
444 
445  // Transform it in a TrajectoryStateOnSurface
446 
447  DetId seedDetId(pTSOD.detId());
448 
449  const GeomDet *gdet = theService->trackingGeometry()->idToDet(seedDetId);
450 
451  TrajectoryStateOnSurface initialState =
452  trajectoryStateTransform::transientState(pTSOD, &(gdet->surface()), &*theService->magneticField());
453 
454  // Get the layer on which the seed relies
455  const DetLayer *initialLayer = theService->detLayerGeometry()->idToLayer(seedDetId);
456 
458 
459  // ask for compatible layers
460  vector<const DetLayer *> detLayers;
461  detLayers =
462  theService->muonNavigationSchool()->compatibleLayers(*initialLayer, *initialState.freeState(), detLayerOrder);
463 
464  TrajectoryStateOnSurface result = initialState;
465  if (!detLayers.empty()) {
466  const DetLayer *finalLayer = detLayers.back();
467  const TrajectoryStateOnSurface propagatedState =
468  theService->propagator(theSeedPropagatorName)->propagate(initialState, finalLayer->surface());
469  if (propagatedState.isValid())
470  result = propagatedState;
471  }
472 
473  return result;
474 }
virtual const BoundSurface & surface() const =0
The surface of the GeometricSearchDet.
void computeResolutionAndPull(TrajectoryStateOnSurface &vtx, SimTrack &simTrack)
Definition: HTrack.cc:117
T perp() const
Definition: PV3DBase.h:69
std::pair< SimTrack, double > getSimTrack(TrajectoryStateOnSurface &tsos, edm::Handle< edm::SimTrackContainer > simTracks)
virtual void setCurrentFolder(std::string const &fullpath)
Definition: DQMStore.cc:32
bool checkMuonSimHitPresence(const edm::Event &event, edm::Handle< edm::SimTrackContainer > simTracks)
T y() const
Definition: PV3DBase.h:60
auto const & tracks
cannot be loose
size_t recHitsSize() const
number of RecHits
PropagationDirection
TrajectoryStateOnSurface getSeedTSOS(const TrajectorySeed &seed)
void seedsAnalysis(const edm::Event &event, const edm::EventSetup &eventSetup, edm::Handle< edm::SimTrackContainer > simTracks)
Definition: sim.h:19
double chi2() const
chi-squared of the fit
MuonTrackAnalyzer(const edm::ParameterSet &pset)
Constructor.
#define LogTrace(id)
tuple result
Definition: mps_fire.py:311
std::string dumpFTS(const FreeTrajectoryState &fts) const
std::string dumpTSOS(const TrajectoryStateOnSurface &tsos) const
ROOT::Math::DisplacementVector3D< ROOT::Math::Cartesian3D< double > > XYZVectorD
spatial vector with cartesian internal representation
Definition: Vector3D.h:8
T sqrt(T t)
Definition: SSEVec.h:19
bool isInTheAcceptance(double eta)
FreeTrajectoryState const * freeState(bool withErrors=true) const
T z() const
Definition: PV3DBase.h:61
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
float ChiSquaredProbability(double chiSquared, double nrDOF)
unsigned int detId() const
void Fill(TrajectoryStateOnSurface &)
Definition: HTrack.cc:104
GlobalVector momentum() const
def all
workaround iterator generators for ROOT classes
Definition: cmstools.py:25
Definition: DetId.h:17
PTrajectoryStateOnDet const & startingState() const
#define debug
Definition: HDRShower.cc:19
TrajectoryStateOnSurface transientState(const PTrajectoryStateOnDet &ts, const Surface *surface, const MagneticField *field)
void bookHistograms(DQMStore::IBooker &, edm::Run const &, edm::EventSetup const &) override
MonitorElement * book2D(TString const &name, TString const &title, int nchX, double lowX, double highX, int nchY, double lowY, double highY, FUNC onbooking=NOOP())
Definition: DQMStore.h:212
T getParameter(std::string const &) const
Definition: ParameterSet.h:303
double normalizedChi2() const
chi-squared divided by n.d.o.f.
std::string const & label() const
Definition: InputTag.h:36
double ndof() const
number of degrees of freedom of the fit
std::string const & process() const
Definition: InputTag.h:40
void tracksAnalysis(const edm::Event &event, const edm::EventSetup &eventSetup, edm::Handle< edm::SimTrackContainer > simTracks)
GlobalVector globalMomentum() const
const math::XYZTLorentzVectorD & momentum() const
Definition: CoreSimTrack.h:19
~MuonTrackAnalyzer() override
Destructor.
void analyze(const edm::Event &event, const edm::EventSetup &eventSetup) override
MonitorElement * book1D(TString const &name, TString const &title, int const nchX, double const lowX, double const highX, FUNC onbooking=NOOP())
Definition: DQMStore.h:98
void FillDeltaR(double)
Definition: HTrack.cc:111
T x() const
Definition: PV3DBase.h:59
Definition: HTrack.h:12
std::string const & instance() const
Definition: InputTag.h:37
void fillPlots(const edm::Event &event, edm::Handle< edm::SimTrackContainer > &simTracks)
Definition: Run.h:45
#define LogDebug(id)