Belle II Software  release-08-00-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 //This module
10 #include <ecl/modules/eclTrackBremFinder/ECLTrackBremFinderModule.h>
11 
12 //Framework
13 #include <framework/dataobjects/EventMetaData.h>
14 #include <framework/logging/Logger.h>
15 #include <framework/gearbox/Const.h>
16 
17 //MDST
18 #include <mdst/dataobjects/ECLCluster.h>
19 #include <mdst/dataobjects/Track.h>
20 #include <mdst/dataobjects/PIDLikelihood.h>
21 #include <mdst/dataobjects/TrackFitResult.h>
22 
23 //Tracking
24 #include <tracking/dataobjects/RecoTrack.h>
25 #include <tracking/dataobjects/BremHit.h>
26 
27 //ECL
28 #include <ecl/modules/eclTrackBremFinder/BestMatchContainer.h>
29 #include <ecl/modules/eclTrackBremFinder/BremFindingMatchCompute.h>
30 
31 
32 using namespace Belle2;
33 
34 REG_MODULE(ECLTrackBremFinder);
35 
37  Module()
38 {
39  setDescription("Use Track direction to pick up possible ECL Brem Cluster");
41 
42  addParam("eclClustersStoreArrayName", m_param_eclClustersStoreArrayName, "StoreArray name of the ECLClusters for brem matching",
44 
45  addParam("tracksStoreArrayName", m_param_tracksStoreArrayName, "StoreArray name of the Tracks for brem matching",
47 
48  addParam("recoTracksStoreArrayName", m_param_recoTracksStoreArrayName, "StoreArray name of the reco tracks used for brem search",
50 
51  addParam("clusterAcceptanceFactor", m_clusterAcceptanceFactor,
52  "Factor which is multiplied onto the cluster position error to check for matches",
54 
55  addParam("virtualHitRadii", m_virtualHitRadii, "Radii where virtual hits for the extrapolation will be generated",
57 
58  addParam("clusterDistanceCut", m_clusterDistanceCut,
59  "Cut on the distance between the cluster position angle and the extrapolation angle",
61 }
62 
64 {
66  m_eclClusters.registerRelationTo(m_eclClusters);
67 
69 
70  const std::string relationName = "Bremsstrahlung";
71  m_eclClusters.registerRelationTo(m_tracks, DataStore::c_Event, DataStore::c_WriteOut, relationName);
72 
74 
75  m_bremHits.registerInDataStore();
76  m_bremHits.registerRelationTo(m_eclClusters);
77  m_bremHits.registerRelationTo(m_recoTracks);
78 }
79 
81 {
82 
83 
84  // either use the Clusters matched to tracks (non-neutral) or use the smarter decision
85  // done by the neutral / non-neutral classification code
86  // todo: there needs to be a global (all tracks vs. all clusters) conflict resolution,
87  // sort tracks by Pt, as high energy tracks are more likely to radiate bremsstrahlung photons
88  // with sufficient energy to be detected and reconstructed
89  for (auto& track : m_tracks) {
90 
91  const TrackFitResult* trackFitResult = track.getTrackFitResult(Const::ChargedStable(211));
92  if (trackFitResult) {
93  double trackMomentum = trackFitResult->getMomentum().R();
94  // if the momentum of the track is higher than 5 GeV, do not use this track
95  if (trackMomentum > 5.0) {
96  B2DEBUG(20, "Track momentum higher than 5GeV! Track is not used for bremsstrahlung finding");
97  continue;
98  }
99  } else {
100  continue;
101  }
102 
103 
104  B2DEBUG(20, "Checking track for related ECLCluster");
105 
106  // searching for an assigned primary cluster
107  ECLCluster* primaryClusterOfTrack = nullptr;
108  auto relatedClustersToTrack =
109  track.getRelationsWith<ECLCluster>
110  (m_param_eclClustersStoreArrayName); //check the cluster hypothesis ID here (take c_nPhotons hypothesis)!!
111  for (auto& relatedCluster : relatedClustersToTrack) {
112  if (relatedCluster.hasHypothesis(ECLCluster::EHypothesisBit::c_nPhotons)) {
113  primaryClusterOfTrack = &relatedCluster;
114  }
115  }
116 
117  // get the RecoTrack to have easy access to individual hits and
118  // their fit state
119  auto recoTrack = track.getRelatedTo<RecoTrack>(m_param_recoTracksStoreArrayName);
120 
121  if (!recoTrack) {
122  // no reco track
123  B2DEBUG(20, "No RecoTrack for this Track");
124  continue;
125  }
126 
127 
128  // set the params for the virtual hits
129  std::vector<std::pair<float, RecoHitInformation*>> extrapolationParams = {};
130  std::vector<genfit::MeasuredStateOnPlane> extrapolatedStates = {};
131  try {
132  for (auto virtualHitRadius : m_virtualHitRadii) {
134  for (auto hit : recoTrack->getRecoHitInformations(true)) {
135  if (hit->useInFit() && recoTrack->hasTrackFitStatus()) {
136  try {
137  auto measState = recoTrack->getMeasuredStateOnPlaneFromRecoHit(hit);
138  float hitRadius = measState.getPos().Perp();
139  float distance = abs(hitRadius - virtualHitRadius);
140  // for higher values the extrapolation will be too bad
141  if (distance < 3) {
142  nearestHitContainer.add(hit, distance);
143  }
144  } catch (NoTrackFitResult&) {
145  B2DEBUG(29, "No track fit result available for this hit! Event: " << m_evtPtr->getEvent());
146  }
147  }
148  if (nearestHitContainer.hasMatch()) {
149  auto nearestHit = nearestHitContainer.getBestMatch();
150  extrapolationParams.push_back({virtualHitRadius, nearestHit});
151  }
152  }
153  }
154 
155  for (auto param : extrapolationParams) {
156  auto fitted_state = recoTrack->getMeasuredStateOnPlaneFromRecoHit(param.second);
157  try {
158  fitted_state.extrapolateToCylinder(param.first);
159  extrapolatedStates.push_back(fitted_state);
160  } catch (genfit::Exception& exception1) {
161  B2DEBUG(20, "Extrapolation failed!");
162  }
163  }
164  } catch (const genfit::Exception& e) {
165  B2WARNING("Exception" << e.what());
166  }
167 
168  // possible improvement: use fast lookup using kd-tree, this is nasty
169  // iterate over full cluster list to find possible compatible clusters
170  for (ECLCluster& cluster : m_eclClusters) {
171  //check if the cluster belongs to a photon or electron
172  if (!cluster.hasHypothesis(ECLCluster::EHypothesisBit::c_nPhotons)) {
173  B2DEBUG(20, "Cluster has wrong hypothesis!");
174  continue;
175  }
176 
177 
178  //check if cluster is already related to a track -> if true, can't be bremsstrahlung cluster
179  auto relatedTrack = cluster.getRelatedFrom<Track>();
180  if (relatedTrack) {
181  B2DEBUG(20, "Cluster already related to track, bailing out");
182  continue;
183  }
184 
185  //check if the cluster is already related to a BremHit
186  //procedure: first come, first served
187  auto relatedBremHit = cluster.getRelated<BremHit>();
188  if (relatedBremHit) {
189  B2DEBUG(20, "Cluster already assumed to be bremsstrahlung cluster!");
190  continue;
191  }
192 
193  typedef std::tuple<ECLCluster*, genfit::MeasuredStateOnPlane, double, double > ClusterMSoPPair;
195 
196  // iterate over all track points and see whether this cluster matches
197  // the track points direction
198  // only VXD hits shall be used
199  for (auto hit : recoTrack->getRecoHitInformations(true)) {
200  if (hit->getTrackingDetector() == RecoHitInformation::c_PXD || hit->getTrackingDetector() == RecoHitInformation::c_SVD) {
201  try {
202  if (!recoTrack->hasTrackFitStatus()) {
203  continue;
204  }
205  auto measState = recoTrack->getMeasuredStateOnPlaneFromRecoHit(hit);
206  auto bremFinder = BremFindingMatchCompute(m_clusterAcceptanceFactor, cluster, measState);
207  if (bremFinder.isMatch()) {
208  ClusterMSoPPair match_pair = std::make_tuple(&cluster, measState, bremFinder.getDistanceHitCluster(),
209  bremFinder.getEffAcceptanceFactor());
210  matchContainer.add(match_pair, bremFinder.getDistanceHitCluster());
211  }
212  } catch (NoTrackFitResult&) {
213  B2DEBUG(29, "No track fit result available for this hit! Event: " << m_evtPtr->getEvent());
214  } catch (genfit::Exception& e) {
215  B2WARNING("Exception" << e.what());
216  }
217  }
218  }
219 
220  // check for matches of the extrapolation of the virtual hits with the cluster position
221  for (auto fitted_state : extrapolatedStates) {
222  auto bremFinder = BremFindingMatchCompute(m_clusterAcceptanceFactor, cluster, fitted_state);
223  if (bremFinder.isMatch()) {
224  ClusterMSoPPair match_pair = std::make_tuple(&cluster, fitted_state, bremFinder.getDistanceHitCluster(),
225  bremFinder.getEffAcceptanceFactor());
226  matchContainer.add(match_pair, bremFinder.getDistanceHitCluster());
227  }
228  }
229 
230 
231  // have we found the best possible track point for this cluster
232  if (matchContainer.hasMatch()) {
233  auto matchClustermSoP = matchContainer.getBestMatch();
234  const auto fitted_state = std::get<1>(matchClustermSoP);
235 
236  const auto fitted_pos = ROOT::Math::XYZVector(fitted_state.getPos());
237  const auto fitted_mom = ROOT::Math::XYZVector(fitted_state.getMom());
238 
239  const auto hit_theta = fitted_mom.Theta();
240  const auto hit_phi = fitted_mom.Phi();
241 
242  B2DEBUG(20, "Best Cluster" << std::endl
243  << " Cluster Phi=" << std::get<0>(matchClustermSoP)->getPhi() << " Theta=" << std::get<0>(matchClustermSoP)->getTheta()
244  << " TrackHit Phi=" << hit_phi << " Theta=" << hit_theta);
245 
246  // create a BremHit if a match is found
247  // relate this BremHit to the bremsstrahlung cluster and the recoTrack
248  // if the track has a primary cluster, add a relation between bremsstrahlung cluster and primary cluster
249 
250  double effAcceptanceFactor = std::get<3>(matchClustermSoP);
251  ECLCluster* bremCluster = std::get<0>(matchClustermSoP);
252  double clusterDistance = std::get<2>(matchClustermSoP);
253 
254  if (fitted_pos.Rho() <= 16 && clusterDistance <= m_clusterDistanceCut) {
255  m_bremHits.appendNew(recoTrack, bremCluster,
256  fitted_pos, bremCluster->getEnergy(ECLCluster::EHypothesisBit::c_nPhotons),
257  clusterDistance, effAcceptanceFactor);
258 
259  // add a relation between the bremsstrahlung cluster and the track to transfer the information to the analysis
260  // set the acceptance factor as weight
261  bremCluster->addRelationTo(&track, effAcceptanceFactor, "Bremsstrahlung");
262 
263  if (primaryClusterOfTrack) {
264  primaryClusterOfTrack->addRelationTo(bremCluster, effAcceptanceFactor);
265  }
266  }
267  }
268  }
269  }
270 }
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.