Belle II Software development
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
26using namespace Belle2;
27
28REG_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 std::vector<ECLCluster*> eclClusters;
77 for (ECLCluster& cluster : m_eclClusters) {
78 /* Check if the cluster belongs to a photon or electron. */
79 if (!cluster.hasHypothesis(ECLCluster::EHypothesisBit::c_nPhotons))
80 continue;
81 /*
82 * Check if the cluster is already related to a track.
83 * If true, it can't be a bremsstrahlung cluster.
84 */
85 const Track* relatedTrack = cluster.getRelatedFrom<Track>();
86 if (relatedTrack != nullptr)
87 continue;
88 eclClusters.push_back(&cluster);
89 }
90
91
92 // either use the Clusters matched to tracks (non-neutral) or use the smarter decision
93 // done by the neutral / non-neutral classification code
94 // todo: there needs to be a global (all tracks vs. all clusters) conflict resolution,
95 // sort tracks by Pt, as high energy tracks are more likely to radiate bremsstrahlung photons
96 // with sufficient energy to be detected and reconstructed
97 for (auto& track : m_tracks) {
98
99 const TrackFitResult* trackFitResult = track.getTrackFitResult(Const::ChargedStable(211));
100 if (trackFitResult) {
101 double trackMomentum = trackFitResult->getMomentum().R();
102 // if the momentum of the track is higher than 5 GeV, do not use this track
103 if (trackMomentum > 5.0) {
104 B2DEBUG(20, "Track momentum higher than 5GeV! Track is not used for bremsstrahlung finding");
105 continue;
106 }
107 } else {
108 continue;
109 }
110
111
112 B2DEBUG(20, "Checking track for related ECLCluster");
113
114 // searching for an assigned primary cluster
115 ECLCluster* primaryClusterOfTrack = nullptr;
116 auto relatedClustersToTrack =
117 track.getRelationsWith<ECLCluster>
118 (m_param_eclClustersStoreArrayName); //check the cluster hypothesis ID here (take c_nPhotons hypothesis)!!
119 for (auto& relatedCluster : relatedClustersToTrack) {
120 if (relatedCluster.hasHypothesis(ECLCluster::EHypothesisBit::c_nPhotons)) {
121 primaryClusterOfTrack = &relatedCluster;
122 }
123 }
124
125 // get the RecoTrack to have easy access to individual hits and
126 // their fit state
127 auto recoTrack = track.getRelatedTo<RecoTrack>(m_param_recoTracksStoreArrayName);
128
129 if (!recoTrack) {
130 // no reco track
131 B2DEBUG(20, "No RecoTrack for this Track");
132 continue;
133 }
134
135 std::vector<RecoHitInformation*> recoHitInformations =
136 recoTrack->getRecoHitInformations(true);
137
138 // set the params for the virtual hits
139 std::vector<std::pair<float, RecoHitInformation*>> extrapolationParams = {};
140 std::vector<genfit::MeasuredStateOnPlane> extrapolatedStates = {};
141 try {
142 for (auto virtualHitRadius : m_virtualHitRadii) {
144 for (RecoHitInformation* hit : recoHitInformations) {
145 if (hit->useInFit() && recoTrack->hasTrackFitStatus()) {
146 try {
147 auto measState = recoTrack->getMeasuredStateOnPlaneFromRecoHit(hit);
148 float hitRadius = measState.getPos().Perp();
149 float distance = abs(hitRadius - virtualHitRadius);
150 // for higher values the extrapolation will be too bad
151 if (distance < 3) {
152 nearestHitContainer.add(hit, distance);
153 }
154 } catch (NoTrackFitResult&) {
155 B2DEBUG(29, "No track fit result available for this hit! Event: " << m_evtPtr->getEvent());
156 }
157 }
158 if (nearestHitContainer.hasMatch()) {
159 auto nearestHit = nearestHitContainer.getBestMatch();
160 extrapolationParams.push_back({virtualHitRadius, nearestHit});
161 }
162 }
163 }
164
165 for (auto param : extrapolationParams) {
166 auto fitted_state = recoTrack->getMeasuredStateOnPlaneFromRecoHit(param.second);
167 try {
168 fitted_state.extrapolateToCylinder(param.first);
169 extrapolatedStates.push_back(fitted_state);
170 } catch (genfit::Exception& exception1) {
171 B2DEBUG(20, "Extrapolation failed!");
172 }
173 }
174 } catch (const genfit::Exception& e) {
175 B2WARNING("Exception" << e.what());
176 }
177
178 // possible improvement: use fast lookup using kd-tree, this is nasty
179 // iterate over full cluster list to find possible compatible clusters
180 for (ECLCluster* cluster : eclClusters) {
181
182 //check if the cluster is already related to a BremHit
183 //procedure: first come, first served
184 auto relatedBremHit = cluster->getRelated<BremHit>();
185 if (relatedBremHit) {
186 B2DEBUG(20, "Cluster already assumed to be bremsstrahlung cluster!");
187 continue;
188 }
189
190 typedef std::tuple<ECLCluster*, genfit::MeasuredStateOnPlane, double, double > ClusterMSoPPair;
192
193 // iterate over all track points and see whether this cluster matches
194 // the track points direction
195 // only VXD hits shall be used
196 for (RecoHitInformation* hit : recoHitInformations) {
197 if (hit->getTrackingDetector() == RecoHitInformation::c_PXD || hit->getTrackingDetector() == RecoHitInformation::c_SVD) {
198 try {
199 if (!recoTrack->hasTrackFitStatus()) {
200 continue;
201 }
202 auto measState = recoTrack->getMeasuredStateOnPlaneFromRecoHit(hit);
203 auto bremFinder = BremFindingMatchCompute(m_clusterAcceptanceFactor, cluster, measState);
204 if (bremFinder.isMatch()) {
205 ClusterMSoPPair match_pair = std::make_tuple(cluster, measState, bremFinder.getDistanceHitCluster(),
206 bremFinder.getEffAcceptanceFactor());
207 matchContainer.add(match_pair, bremFinder.getDistanceHitCluster());
208 }
209 } catch (NoTrackFitResult&) {
210 B2DEBUG(29, "No track fit result available for this hit! Event: " << m_evtPtr->getEvent());
211 } catch (genfit::Exception& e) {
212 B2WARNING("Exception" << e.what());
213 }
214 }
215 }
216
217 // check for matches of the extrapolation of the virtual hits with the cluster position
218 for (auto fitted_state : extrapolatedStates) {
219 auto bremFinder = BremFindingMatchCompute(m_clusterAcceptanceFactor, cluster, fitted_state);
220 if (bremFinder.isMatch()) {
221 ClusterMSoPPair match_pair = std::make_tuple(cluster, fitted_state, bremFinder.getDistanceHitCluster(),
222 bremFinder.getEffAcceptanceFactor());
223 matchContainer.add(match_pair, bremFinder.getDistanceHitCluster());
224 }
225 }
226
227
228 // have we found the best possible track point for this cluster
229 if (matchContainer.hasMatch()) {
230 auto matchClustermSoP = matchContainer.getBestMatch();
231 const auto fitted_state = std::get<1>(matchClustermSoP);
232
233 const auto fitted_pos = ROOT::Math::XYZVector(fitted_state.getPos());
234 const auto fitted_mom = ROOT::Math::XYZVector(fitted_state.getMom());
235
236 const auto hit_theta = fitted_mom.Theta();
237 const auto hit_phi = fitted_mom.Phi();
238
239 B2DEBUG(20, "Best Cluster" << std::endl
240 << " Cluster Phi=" << std::get<0>(matchClustermSoP)->getPhi() << " Theta=" << std::get<0>(matchClustermSoP)->getTheta()
241 << " TrackHit Phi=" << hit_phi << " Theta=" << hit_theta);
242
243 // create a BremHit if a match is found
244 // relate this BremHit to the bremsstrahlung cluster and the recoTrack
245 // if the track has a primary cluster, add a relation between bremsstrahlung cluster and primary cluster
246
247 double effAcceptanceFactor = std::get<3>(matchClustermSoP);
248 ECLCluster* bremCluster = std::get<0>(matchClustermSoP);
249 double clusterDistance = std::get<2>(matchClustermSoP);
250
251 if (fitted_pos.Rho() <= 16 && clusterDistance <= m_clusterDistanceCut) {
252 m_bremHits.appendNew(recoTrack, bremCluster,
253 fitted_pos, bremCluster->getEnergy(ECLCluster::EHypothesisBit::c_nPhotons),
254 clusterDistance, effAcceptanceFactor);
255
256 // add a relation between the bremsstrahlung cluster and the track to transfer the information to the analysis
257 // set the acceptance factor as weight
258 bremCluster->addRelationTo(&track, effAcceptanceFactor, "Bremsstrahlung");
259
260 if (primaryClusterOfTrack) {
261 primaryClusterOfTrack->addRelationTo(bremCluster, effAcceptanceFactor);
262 }
263 }
264 }
265 }
266 }
267}
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:589
@ 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 class stores additional information to every CDC/SVD/PXD hit stored in a RecoTrack.
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
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.