Belle II Software  release-06-02-00
V0FinderModule.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 #include <tracking/modules/V0Finder/V0FinderModule.h>
9 
10 #include <framework/gearbox/Const.h>
11 #include <framework/logging/Logger.h>
12 #include <framework/core/ModuleParam.templateDetails.h> // needed for complicated parameter types
13 
14 #include <tracking/dataobjects/RecoTrack.h>
15 
16 using namespace Belle2;
17 
18 REG_MODULE(V0Finder);
19 
21 {
22  setDescription("This is a simple V0 finder which matches all positive "
23  "tracks with all negative tracks, fitting a vertex for each "
24  "pair. Depending on the outcome of each fit, a corresponding "
25  "Belle2::V0 is stored or not.\n\n"
26 
27  "No V0s with vertex inside the beam pipe "
28  "are saved. They are recovered in a following step.\n\n"
29 
30  "Outside the beam pipe only a chi^2 cut is applied "
31  "('vertexChi2CutOutside').\n"
32  "The value used as beam pipe radius is a parameter and "
33  "can be changed.");
34 
36 
37  //input tracks
38  addParam("RecoTracks", m_arrayNameRecoTrack,
39  "RecoTrack StoreArray name (input)", std::string(""));
40  addParam("CopiedRecoTracks", m_arrayNameCopiedRecoTrack,
41  "RecoTrack StoreArray name (used for track refitting)", std::string("CopiedRecoTracks"));
42  addParam("TrackFitResults", m_arrayNameTFResult,
43  "Belle2::TrackFitResult StoreArray name (in- and output).\n"
44  "Note that the V0s use pointers indices into these arrays, so all hell may break loose, "
45  "if you change this.", std::string(""));
46  addParam("Tracks", m_arrayNameTrack,
47  "Belle2::Track StoreArray name (input).\n"
48  "Note that the V0s use pointers indices into these arrays, so all hell may break loose, "
49  "if you change this.", std::string(""));
50 
51  // output: V0s
52  addParam("V0s", m_arrayNameV0, "V0 StoreArry name (output).", std::string(""));
53  addParam("Validation", m_validation, "Create output for validation.", bool(false));
54  addParam("V0ValidationVertices", m_arrayNameV0ValidationVertex, "V0ValidationVertex StoreArray name (optional output)",
55  std::string(""));
56 
57  addParam("beamPipeRadius", m_beamPipeRadius,
58  "Radius at which we switch between the two classes of cuts. "
59  "The default is a little inside the beam pipe to allow some tolerance.",
60  1.);
61 
62  addParam("vertexChi2CutOutside", m_vertexChi2CutOutside,
63  "Maximum chiĀ² for the vertex fit (NDF = 1)", 10000.);
64 
65  addParam("invMassRangeKshort", m_invMassRangeKshort,
66  "mass range in GeV for reconstructed Kshort after removing material effects and inner hits", m_invMassRangeKshort);
67 
68  addParam("invMassRangeLambda", m_invMassRangeLambda,
69  "mass range in GeV for reconstructed Lambda after removing material effects and inner hits", m_invMassRangeLambda);
70 
71  addParam("invMassRangePhoton", m_invMassRangePhoton,
72  "mass range in GeV for reconstructed Photon after removing material effects and inner hits", m_invMassRangePhoton);
73 
74  addParam("v0FitterMode", m_v0FitterMode,
75  "designate which fitAndStore function is called in V0Fitter.\n"
76  " 0: store V0 at the first vertex fit, regardless of inner hits \n"
77  " 1: remove hits inside the V0 vertex position\n"
78  " 2: mode 2 + don't use SVD hits if there is only one available SVD hit-pair (default)",
79  1);
80 
81  addParam("massRangeKshort", m_preFilterMassRangeKshort,
82  "mass range in GeV for reconstructed Kshort used for pre-selection of candidates"
83  " (to be chosen loosely as used momenta ignore material effects)", m_preFilterMassRangeKshort);
84  addParam("massRangeLambda", m_preFilterMassRangeLambda,
85  "mass range in GeV for reconstructed Lambda used for pre-selection of candidates"
86  " (to be chosen loosely as used momenta ignore material effects)", m_preFilterMassRangeLambda);
87 }
88 
89 
91 {
92  m_tracks.isRequired(m_arrayNameTrack);
94  m_tracks.requireRelationTo(recoTracks);
95  //All the other required StoreArrays are checked in the Construtor of the V0Fitter.
96  m_v0Fitter = std::make_unique<V0Fitter>(m_arrayNameTFResult, m_arrayNameV0,
99 
102  m_v0Fitter->setFitterMode(m_v0FitterMode);
103 
104  // safeguard for users that try to break the code
105  if (std::get<0>(m_preFilterMassRangeKshort) > std::get<1>(m_preFilterMassRangeKshort)) {
106  B2FATAL("The minimum has to be smaller than the maximum of the Kshort mass range! min = " << std::get<0>
107  (m_preFilterMassRangeKshort) << " max = " << std::get<1>(m_preFilterMassRangeKshort));
108  }
109  if (std::get<0>(m_preFilterMassRangeLambda) > std::get<1>(m_preFilterMassRangeLambda)) {
110  B2FATAL("The minimum has to be smaller than the maximum of the Lambda mass range! min = " << std::get<0>
111  (m_preFilterMassRangeLambda) << " max = " << std::get<1>(m_preFilterMassRangeLambda));
112  }
113 
114  // precalculate the mass range squared
115  m_mKshortMin2 = std::get<0>(m_preFilterMassRangeKshort) < 0 ? -std::get<0>(m_preFilterMassRangeKshort) * std::get<0>
116  (m_preFilterMassRangeKshort) : std::get<0>
118  m_mKshortMax2 = std::get<1>(m_preFilterMassRangeKshort) < 0 ? -std::get<1>(m_preFilterMassRangeKshort) * std::get<1>
119  (m_preFilterMassRangeKshort) : std::get<1>
121  m_mLambdaMin2 = std::get<0>(m_preFilterMassRangeLambda) < 0 ? -std::get<0>(m_preFilterMassRangeLambda) * std::get<0>
122  (m_preFilterMassRangeLambda) : std::get<0>
124  m_mLambdaMax2 = std::get<1>(m_preFilterMassRangeLambda) < 0 ? -std::get<1>(m_preFilterMassRangeLambda) * std::get<1>
125  (m_preFilterMassRangeLambda) : std::get<1>
127 
128 }
129 
130 
132 {
133  B2DEBUG(200, m_tracks.getEntries() << " tracks in event.");
134 
135  // Group tracks into positive and negative tracks.
136  std::vector<const Track*> tracksPlus;
137  tracksPlus.reserve(m_tracks.getEntries());
138 
139  std::vector<const Track*> tracksMinus;
140  tracksMinus.reserve(m_tracks.getEntries());
141 
142  for (const auto& track : m_tracks) {
143  RecoTrack const* const recoTrack = track.getRelated<RecoTrack>();
144  B2ASSERT("No RecoTrack available for given Track.", recoTrack);
145 
146  if (recoTrack->getChargeSeed() > 0) {
147  tracksPlus.push_back(&track);
148  }
149  if (recoTrack->getChargeSeed() < 0) {
150  tracksMinus.push_back(&track);
151  }
152  }
153 
154  // Reject boring events.
155  if (tracksPlus.empty() || tracksMinus.empty()) {
156  B2DEBUG(200, "No interesting track pairs. tracksPlus " << tracksPlus.size() << ", tracksMinus " << tracksMinus.size());
157  return;
158  }
159 
160 
161  // Pair up each positive track with each negative track.
162  for (auto& trackPlus : tracksPlus) {
163  for (auto& trackMinus : tracksMinus) {
164  bool isForceStored, isHitRemoved;
165  try {
166  if (preFilterTracks(trackPlus, trackMinus, Const::Kshort)) {
167  m_v0Fitter->fitAndStore(trackPlus, trackMinus, Const::Kshort, isForceStored, isHitRemoved);
168  m_nForceStored += isForceStored;
169  m_nHitRemoved += isHitRemoved;
170  }
171  } catch (const genfit::Exception& e) {
172  // genfit exception raised, skip this track pair for this hypothesis
173  B2WARNING("Genfit exception caught. Skipping this track pair for Kshort hypothesis. " << LogVar("Genfit exception:", e.what()));
174  }
175 
176  try {
177  // the pre-filter is not able to reject photons, so no need to apply pre filter for photons
178  m_v0Fitter->fitAndStore(trackPlus, trackMinus, Const::photon, isForceStored, isHitRemoved);
179  m_nForceStored += isForceStored;
180  m_nHitRemoved += isHitRemoved;
181  } catch (const genfit::Exception& e) {
182  // genfit exception raised, skip this track pair for this hypothesis
183  B2WARNING("Genfit exception caught. Skipping this track pair for photon hypothesis. " << LogVar("Genfit exception:", e.what()));
184  }
185 
186  try {
187  if (preFilterTracks(trackPlus, trackMinus, Const::Lambda)) {
188  m_v0Fitter->fitAndStore(trackPlus, trackMinus, Const::Lambda, isForceStored, isHitRemoved);
189  m_nForceStored += isForceStored;
190  m_nHitRemoved += isHitRemoved;
191  }
192  } catch (const genfit::Exception& e) {
193  // genfit exception raised, skip this track pair for this hypothesis
194  B2WARNING("Genfit exception caught. Skipping this track pair for Lambda hypothesis. " << LogVar("Genfit exception:", e.what()));
195  }
196 
197  try {
198  if (preFilterTracks(trackPlus, trackMinus, Const::antiLambda)) {
199  m_v0Fitter->fitAndStore(trackPlus, trackMinus, Const::antiLambda, isForceStored, isHitRemoved);
200  m_nForceStored += isForceStored;
201  m_nHitRemoved += isHitRemoved;
202  }
203  } catch (const genfit::Exception& e) {
204  // genfit exception raised, skip this track pair for this hypothesis
205  B2WARNING("Genfit exception caught. Skipping this track pair for anti-Lambda hypothesis. " << LogVar("Genfit exception:",
206  e.what()));
207  }
208  }
209  }
210 
211 }
212 
214 {
215  B2INFO("===V0Finder summary=============================================================");
216  B2INFO("In total " << m_nHitRemoved + m_nForceStored << " saved V0s have inner hits.");
217  B2INFO("- Inner hits successfully removed in " << m_nHitRemoved << " V0s.");
218  B2INFO("- The hit removal failed in " << m_nForceStored << " V0s, instead V0s before removing inner hits saved.");
219 }
220 
221 bool
222 V0FinderModule::preFilterTracks(const Track* trackPlus, const Track* trackMinus, const Const::ParticleType& v0Hypothesis)
223 {
224  const double* range_m2_min = nullptr;
225  const double* range_m2_max = nullptr;
226  if (v0Hypothesis == Const::Kshort) {
227  range_m2_min = &m_mKshortMin2;
228  range_m2_max = &m_mKshortMax2;
229  } else if (v0Hypothesis == Const::Lambda or v0Hypothesis == Const::antiLambda) {
230  range_m2_min = &m_mLambdaMin2;
231  range_m2_max = &m_mLambdaMax2;
232  } else {
233  // this case is not covered so accept everything
234  return true;
235  }
236 
237  const auto trackHypotheses = m_v0Fitter->getTrackHypotheses(v0Hypothesis);
238 
239  // first track should always be the positve one
240  double m_plus = trackHypotheses.first.getMass();
241  double p_plus = trackPlus->getTrackFitResultWithClosestMass(trackHypotheses.first)->getMomentum().Mag();
242  double E_plus = sqrt(m_plus * m_plus + p_plus * p_plus);
243 
244  // second track is the negative
245  double m_minus = trackHypotheses.second.getMass();
246  double p_minus = trackMinus->getTrackFitResultWithClosestMass(trackHypotheses.second)->getMomentum().Mag();
247  double E_minus = sqrt(m_minus * m_minus + p_minus * p_minus);
248 
249  // now do the adding of the 4momenta
250  double sum_E2 = (E_minus + E_plus) * (E_minus + E_plus);
251 
252  // the minimal/maximal allowed mass for these 4momenta is given if the 3momenta are aligned ( cos(angle)= +/- 1 )
253  double candmass_min2 = sum_E2 - (p_plus + p_minus) * (p_plus + p_minus);
254  double candmass_max2 = sum_E2 - (p_plus - p_minus) * (p_plus - p_minus);
255 
256  // if true possible candiate mass overlaps with the user specified range
257  bool in_range = candmass_max2 > *range_m2_min and candmass_min2 < *range_m2_max;
258 
259  return in_range;
260 }
The ParticleType class for identifying different particle types.
Definition: Const.h:289
static const ParticleType Lambda
Lambda particle.
Definition: Const.h:559
static const ParticleType antiLambda
Anti-Lambda particle.
Definition: Const.h:560
static const ParticleType Kshort
K^0_S particle.
Definition: Const.h:557
static const ParticleType photon
photon particle
Definition: Const.h:554
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 is the Reconstruction Event-Data Model Track.
Definition: RecoTrack.h:76
short int getChargeSeed() const
Return the charge seed stored in the reco track. ATTENTION: This is not the fitted charge.
Definition: RecoTrack.h:496
Accessor to arrays stored in the data store.
Definition: StoreArray.h:113
TVector3 getMomentum() const
Getter for vector of momentum at closest approach of track in r/phi projection.
Class that bundles various TrackFitResults.
Definition: Track.h:25
const TrackFitResult * getTrackFitResultWithClosestMass(const Const::ChargedStable &requestedType) const
Return the track fit for a fit hypothesis with the closest mass.
Definition: Track.cc:68
std::tuple< double, double > m_preFilterMassRangeKshort
range for reconstructed Kshort mass used for pre-selection default range set to nominal KS mass + 0....
std::string m_arrayNameCopiedRecoTrack
StoreArray name of the RecoTracks.
std::string m_arrayNameV0
StoreArray name of the V0 (Output).
void initialize() override
Registration of StoreArrays, Relations, check proper GenFit setup.
bool m_validation
Flag if use validation.
std::tuple< double, double > m_preFilterMassRangeLambda
range for reconstructed Lambda mass used for pre-selection Default range set to nominal Lambda mass +...
void event() override
Creates Belle2::V0s from Belle2::Tracks as described in the class documentation.
std::string m_arrayNameTFResult
StoreArray name of the TrackFitResults (In- and Output).
double m_mKshortMax2
pre-calculated maximum Kshort mass squared
std::string m_arrayNameV0ValidationVertex
StoreArray name of the V0ValidationVertex.
void terminate() override
Prints status summary.
double m_mLambdaMin2
pre-calculated mininum Lambda mass squared
double m_beamPipeRadius
Radius where inside/outside beampipe is defined.
V0FinderModule()
Setting of module description, parameters.
double m_mLambdaMax2
pre-calculated maximum Lambda mass squared
std::tuple< double, double > m_invMassRangePhoton
range for reconstructed Photon mass used after removing material effects and inner hits default range...
std::unique_ptr< V0Fitter > m_v0Fitter
Object containing the actual algorithm.
StoreArray< Track > m_tracks
Actually array of mdst Tracks.
double m_vertexChi2CutOutside
Chi2 cut for V0s outside of the beampipe. Applies to all.
std::string m_arrayNameRecoTrack
StoreArray name of the RecoTracks (Input).
bool preFilterTracks(const Track *trackPlus, const Track *trackMinus, const Const::ParticleType &v0Hypothesis)
helper function that gets the approximate mass range for the two given tracks and rejects candidates ...
int m_v0FitterMode
fitter mode (0: store V0 at the first vertex fit, regardless of inner hits, 1: remove hits inside the...
std::tuple< double, double > m_invMassRangeKshort
range for reconstructed Kshort mass used after removing material effects and inner hits default range...
std::tuple< double, double > m_invMassRangeLambda
range for reconstructed Lambda mass used after removing material effects and inner hits default range...
std::string m_arrayNameTrack
StoreArray name of the Tracks (Input).
double m_mKshortMin2
pre-calculated mininum Kshort mass squared
Class to store variables with their name which were sent to the logging service.
Exception class for error handling in GENFIT (provides storage for diagnostic information)
Definition: Exception.h:48
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
Abstract base class for different kinds of events.