Belle II Software  release-08-01-10
ECLTrackBremFinderModule.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 /* Own header. */
10 #include <ecl/modules/eclTrackBremFinder/ECLTrackBremFinderModule.h>
11 
12 /* ECL headers. */
13 #include <ecl/modules/eclTrackBremFinder/BestMatchContainer.h>
14 #include <ecl/modules/eclTrackBremFinder/BremFindingMatchCompute.h>
15 
16 /* Basf2 headers. */
17 #include <framework/dataobjects/EventMetaData.h>
18 #include <framework/logging/Logger.h>
19 #include <framework/gearbox/Const.h>
20 #include <mdst/dataobjects/ECLCluster.h>
21 #include <mdst/dataobjects/Track.h>
22 #include <mdst/dataobjects/TrackFitResult.h>
23 #include <tracking/dataobjects/RecoTrack.h>
24 #include <tracking/dataobjects/BremHit.h>
25 
26 using namespace Belle2;
27 
28 REG_MODULE(ECLTrackBremFinder);
29 
31  Module()
32 {
33  setDescription("Use Track direction to pick up possible ECL Brem Cluster");
35 
36  addParam("eclClustersStoreArrayName", m_param_eclClustersStoreArrayName, "StoreArray name of the ECLClusters for brem matching",
38 
39  addParam("tracksStoreArrayName", m_param_tracksStoreArrayName, "StoreArray name of the Tracks for brem matching",
41 
42  addParam("recoTracksStoreArrayName", m_param_recoTracksStoreArrayName, "StoreArray name of the reco tracks used for brem search",
44 
45  addParam("clusterAcceptanceFactor", m_clusterAcceptanceFactor,
46  "Factor which is multiplied onto the cluster position error to check for matches",
48 
49  addParam("virtualHitRadii", m_virtualHitRadii, "Radii where virtual hits for the extrapolation will be generated",
51 
52  addParam("clusterDistanceCut", m_clusterDistanceCut,
53  "Cut on the distance between the cluster position angle and the extrapolation angle",
55 }
56 
58 {
60  m_eclClusters.registerRelationTo(m_eclClusters);
61 
63 
64  const std::string relationName = "Bremsstrahlung";
65  m_eclClusters.registerRelationTo(m_tracks, DataStore::c_Event, DataStore::c_WriteOut, relationName);
66 
68 
69  m_bremHits.registerInDataStore();
70  m_bremHits.registerRelationTo(m_eclClusters);
71  m_bremHits.registerRelationTo(m_recoTracks);
72 }
73 
75 {
76 
77 
78  // either use the Clusters matched to tracks (non-neutral) or use the smarter decision
79  // done by the neutral / non-neutral classification code
80  // todo: there needs to be a global (all tracks vs. all clusters) conflict resolution,
81  // sort tracks by Pt, as high energy tracks are more likely to radiate bremsstrahlung photons
82  // with sufficient energy to be detected and reconstructed
83  for (auto& track : m_tracks) {
84 
85  const TrackFitResult* trackFitResult = track.getTrackFitResult(Const::ChargedStable(211));
86  if (trackFitResult) {
87  double trackMomentum = trackFitResult->getMomentum().R();
88  // if the momentum of the track is higher than 5 GeV, do not use this track
89  if (trackMomentum > 5.0) {
90  B2DEBUG(20, "Track momentum higher than 5GeV! Track is not used for bremsstrahlung finding");
91  continue;
92  }
93  } else {
94  continue;
95  }
96 
97 
98  B2DEBUG(20, "Checking track for related ECLCluster");
99 
100  // searching for an assigned primary cluster
101  ECLCluster* primaryClusterOfTrack = nullptr;
102  auto relatedClustersToTrack =
103  track.getRelationsWith<ECLCluster>
104  (m_param_eclClustersStoreArrayName); //check the cluster hypothesis ID here (take c_nPhotons hypothesis)!!
105  for (auto& relatedCluster : relatedClustersToTrack) {
106  if (relatedCluster.hasHypothesis(ECLCluster::EHypothesisBit::c_nPhotons)) {
107  primaryClusterOfTrack = &relatedCluster;
108  }
109  }
110 
111  // get the RecoTrack to have easy access to individual hits and
112  // their fit state
113  auto recoTrack = track.getRelatedTo<RecoTrack>(m_param_recoTracksStoreArrayName);
114 
115  if (!recoTrack) {
116  // no reco track
117  B2DEBUG(20, "No RecoTrack for this Track");
118  continue;
119  }
120 
121 
122  // set the params for the virtual hits
123  std::vector<std::pair<float, RecoHitInformation*>> extrapolationParams = {};
124  std::vector<genfit::MeasuredStateOnPlane> extrapolatedStates = {};
125  try {
126  for (auto virtualHitRadius : m_virtualHitRadii) {
128  for (auto hit : recoTrack->getRecoHitInformations(true)) {
129  if (hit->useInFit() && recoTrack->hasTrackFitStatus()) {
130  try {
131  auto measState = recoTrack->getMeasuredStateOnPlaneFromRecoHit(hit);
132  float hitRadius = measState.getPos().Perp();
133  float distance = abs(hitRadius - virtualHitRadius);
134  // for higher values the extrapolation will be too bad
135  if (distance < 3) {
136  nearestHitContainer.add(hit, distance);
137  }
138  } catch (NoTrackFitResult&) {
139  B2DEBUG(29, "No track fit result available for this hit! Event: " << m_evtPtr->getEvent());
140  }
141  }
142  if (nearestHitContainer.hasMatch()) {
143  auto nearestHit = nearestHitContainer.getBestMatch();
144  extrapolationParams.push_back({virtualHitRadius, nearestHit});
145  }
146  }
147  }
148 
149  for (auto param : extrapolationParams) {
150  auto fitted_state = recoTrack->getMeasuredStateOnPlaneFromRecoHit(param.second);
151  try {
152  fitted_state.extrapolateToCylinder(param.first);
153  extrapolatedStates.push_back(fitted_state);
154  } catch (genfit::Exception& exception1) {
155  B2DEBUG(20, "Extrapolation failed!");
156  }
157  }
158  } catch (const genfit::Exception& e) {
159  B2WARNING("Exception" << e.what());
160  }
161 
162  // possible improvement: use fast lookup using kd-tree, this is nasty
163  // iterate over full cluster list to find possible compatible clusters
164  for (ECLCluster& cluster : m_eclClusters) {
165  //check if the cluster belongs to a photon or electron
166  if (!cluster.hasHypothesis(ECLCluster::EHypothesisBit::c_nPhotons)) {
167  B2DEBUG(20, "Cluster has wrong hypothesis!");
168  continue;
169  }
170 
171 
172  //check if cluster is already related to a track -> if true, can't be bremsstrahlung cluster
173  auto relatedTrack = cluster.getRelatedFrom<Track>();
174  if (relatedTrack) {
175  B2DEBUG(20, "Cluster already related to track, bailing out");
176  continue;
177  }
178 
179  //check if the cluster is already related to a BremHit
180  //procedure: first come, first served
181  auto relatedBremHit = cluster.getRelated<BremHit>();
182  if (relatedBremHit) {
183  B2DEBUG(20, "Cluster already assumed to be bremsstrahlung cluster!");
184  continue;
185  }
186 
187  typedef std::tuple<ECLCluster*, genfit::MeasuredStateOnPlane, double, double > ClusterMSoPPair;
189 
190  // iterate over all track points and see whether this cluster matches
191  // the track points direction
192  // only VXD hits shall be used
193  for (auto hit : recoTrack->getRecoHitInformations(true)) {
194  if (hit->getTrackingDetector() == RecoHitInformation::c_PXD || hit->getTrackingDetector() == RecoHitInformation::c_SVD) {
195  try {
196  if (!recoTrack->hasTrackFitStatus()) {
197  continue;
198  }
199  auto measState = recoTrack->getMeasuredStateOnPlaneFromRecoHit(hit);
200  auto bremFinder = BremFindingMatchCompute(m_clusterAcceptanceFactor, cluster, measState);
201  if (bremFinder.isMatch()) {
202  ClusterMSoPPair match_pair = std::make_tuple(&cluster, measState, bremFinder.getDistanceHitCluster(),
203  bremFinder.getEffAcceptanceFactor());
204  matchContainer.add(match_pair, bremFinder.getDistanceHitCluster());
205  }
206  } catch (NoTrackFitResult&) {
207  B2DEBUG(29, "No track fit result available for this hit! Event: " << m_evtPtr->getEvent());
208  } catch (genfit::Exception& e) {
209  B2WARNING("Exception" << e.what());
210  }
211  }
212  }
213 
214  // check for matches of the extrapolation of the virtual hits with the cluster position
215  for (auto fitted_state : extrapolatedStates) {
216  auto bremFinder = BremFindingMatchCompute(m_clusterAcceptanceFactor, cluster, fitted_state);
217  if (bremFinder.isMatch()) {
218  ClusterMSoPPair match_pair = std::make_tuple(&cluster, fitted_state, bremFinder.getDistanceHitCluster(),
219  bremFinder.getEffAcceptanceFactor());
220  matchContainer.add(match_pair, bremFinder.getDistanceHitCluster());
221  }
222  }
223 
224 
225  // have we found the best possible track point for this cluster
226  if (matchContainer.hasMatch()) {
227  auto matchClustermSoP = matchContainer.getBestMatch();
228  const auto fitted_state = std::get<1>(matchClustermSoP);
229 
230  const auto fitted_pos = ROOT::Math::XYZVector(fitted_state.getPos());
231  const auto fitted_mom = ROOT::Math::XYZVector(fitted_state.getMom());
232 
233  const auto hit_theta = fitted_mom.Theta();
234  const auto hit_phi = fitted_mom.Phi();
235 
236  B2DEBUG(20, "Best Cluster" << std::endl
237  << " Cluster Phi=" << std::get<0>(matchClustermSoP)->getPhi() << " Theta=" << std::get<0>(matchClustermSoP)->getTheta()
238  << " TrackHit Phi=" << hit_phi << " Theta=" << hit_theta);
239 
240  // create a BremHit if a match is found
241  // relate this BremHit to the bremsstrahlung cluster and the recoTrack
242  // if the track has a primary cluster, add a relation between bremsstrahlung cluster and primary cluster
243 
244  double effAcceptanceFactor = std::get<3>(matchClustermSoP);
245  ECLCluster* bremCluster = std::get<0>(matchClustermSoP);
246  double clusterDistance = std::get<2>(matchClustermSoP);
247 
248  if (fitted_pos.Rho() <= 16 && clusterDistance <= m_clusterDistanceCut) {
249  m_bremHits.appendNew(recoTrack, bremCluster,
250  fitted_pos, bremCluster->getEnergy(ECLCluster::EHypothesisBit::c_nPhotons),
251  clusterDistance, effAcceptanceFactor);
252 
253  // add a relation between the bremsstrahlung cluster and the track to transfer the information to the analysis
254  // set the acceptance factor as weight
255  bremCluster->addRelationTo(&track, effAcceptanceFactor, "Bremsstrahlung");
256 
257  if (primaryClusterOfTrack) {
258  primaryClusterOfTrack->addRelationTo(bremCluster, effAcceptanceFactor);
259  }
260  }
261  }
262  }
263  }
264 }
Multiple entries can be added, but only the one will be kept, which has the best quality estimator.
TItem const & getBestMatch() const
bool add(TItem item, TEstimator est, EstimatorComparison estComparison=[](TEstimator currentBest, TEstimator newEst) {return newEst< currentBest;})
Add a new item with an estimator value.
Module to compute if an extrapolation to the ECL matches the position of an secondary ECLCLuster to f...
A bremsstrahlung hit that correlates an ECLCluster with a RecoTrack.
Definition: BremHit.h:24
Provides a type-safe way to pass members of the chargedStableSet set.
Definition: Const.h:580
@ c_WriteOut
Object/array should be saved by output modules.
Definition: DataStore.h:70
@ c_Event
Different object in each event, all objects/arrays are invalidated after event() function has been ca...
Definition: DataStore.h:59
ECL cluster data.
Definition: ECLCluster.h:27
double getEnergy(EHypothesisBit hypothesis) const
Return Energy (GeV).
Definition: ECLCluster.cc:23
@ c_nPhotons
CR is split into n photons (N1)
virtual void initialize() override
Use this to initialize resources or memory your module needs.
std::vector< float > m_virtualHitRadii
Radii where virtual hits for the extrapolation will be generated The default values are taken from br...
virtual void event() override
Called once for each event.
StoreArray< BremHit > m_bremHits
StoreArray BremHits.
double m_clusterAcceptanceFactor
Factor which is multiplied onto the cluster position error to check for matches.
StoreObjPtr< EventMetaData > m_evtPtr
StoreObjPtr EventMetaData.
std::string m_param_tracksStoreArrayName
StoreArray name of the Tracks for brem matching.
StoreArray< Track > m_tracks
StoreArray Track.
std::string m_param_recoTracksStoreArrayName
StoreArray name of the RecoTracks for brem matching.
StoreArray< ECLCluster > m_eclClusters
StoreArray ECLCluster.
std::string m_param_eclClustersStoreArrayName
StoreArray name of the ECLClusters for brem matching.
StoreArray< RecoTrack > m_recoTracks
StoreArray RecoTrack.
ECLTrackBremFinderModule()
Constructor, for setting module description and parameters.
float m_clusterDistanceCut
Cut on the distance between the cluster position angle and the extrapolation angle.
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:79
void addRelationTo(const RelationsInterface< BASE > *object, float weight=1.0, const std::string &namedRelation="") const
Add a relation from this object to another object (with caching).
bool isRequired(const std::string &name="")
Ensure this array/object has been registered previously.
Values of the result of a track fit with a given particle hypothesis.
ROOT::Math::XYZVector 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
Exception class for error handling in GENFIT (provides storage for diagnostic information)
Definition: Exception.h:48
REG_MODULE(arichBtest)
Register the Module.
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
Abstract base class for different kinds of events.