Belle II Software development
PostMergeUpdaterModule.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#include <analysis/modules/PostMergeUpdate/PostMergeUpdaterModule.h>
10#include <mdst/dbobjects/BeamSpot.h>
11#include <framework/logging/Logger.h>
12#include <analysis/utility/RotationTools.h>
13#include <analysis/utility/PCmsLabTransform.h>
14#include <TDatabasePDG.h>
15#include <Math/Vector3D.h>
16
17using namespace Belle2;
18
19//-----------------------------------------------------------------
20// Register module
21//-----------------------------------------------------------------
22REG_MODULE(PostMergeUpdater);
23
24// Implementation
26{
27 setDescription("Synchronize parts of the events post merge/embedding. Used in the signal embedding pipeline. Uses kinematic information for the tag / simulated decay stored in eventExtraInfo.");
28 addParam("Mixing", m_mixing, "Mixing (true) or embedding (false) corrections", false);
29 addParam("isCharged", m_isCharged, "Charged (true) or neutral (false) B mesons", true);
30}
31
33{
34 m_mergedArrayIndices.isRequired("MergedArrayIndices");
35 m_eventExtraInfo.isRequired("EventExtraInfo_indepPath"); // indepPath suffix is hardwired for the second part of the event
36 m_eventExtraInfo_orig.isRequired("EventExtraInfo"); // original extra info
37 m_trackFits.isOptional();
38 m_tracks.isOptional();
39 m_eclclusters.isOptional();
40}
41
43{
44 // Unit rotation:
45 TRotation rot;
46
47 if (
48 m_eventExtraInfo_orig->hasExtraInfo("PX")
49 and m_eventExtraInfo_orig->hasExtraInfo("PY")
50 and m_eventExtraInfo_orig->hasExtraInfo("PZ")
51 and m_eventExtraInfo->hasExtraInfo("PX")
52 and m_eventExtraInfo->hasExtraInfo("PY")
53 and m_eventExtraInfo->hasExtraInfo("PZ")
54 ) {
55 // For embedding, we will rotate the simulated B in the direction of the reconstructed tag
56 B2Vector3D tag3v = B2Vector3D(m_eventExtraInfo_orig->getExtraInfo("PX"),
57 m_eventExtraInfo_orig->getExtraInfo("PY"),
58 m_eventExtraInfo_orig->getExtraInfo("PZ")
59 );
60
61 B2Vector3D sec3v = B2Vector3D(m_eventExtraInfo->getExtraInfo("PX"),
62 m_eventExtraInfo->getExtraInfo("PY"),
63 m_eventExtraInfo->getExtraInfo("PZ")
64 );
65
66 // For mixing, we want to get an opposite direction, the secondary ROE should point in the direction of the primary TAG
67 if (m_mixing) {
69
70 const int iPDG = m_isCharged ? 521 : 511 ;
71 const double mB = TDatabasePDG::Instance()->GetParticle(iPDG)->Mass();
72 double E = sqrt(mB * mB + sec3v.Mag2());
73 ROOT::Math::PxPyPzEVector sec4v(sec3v.X(), sec3v.Y(), sec3v.Z(), E);
74 ROOT::Math::PxPyPzEVector secCMS = T.labToCms(sec4v);
75
76 // reflection:
77 ROOT::Math::PxPyPzEVector secRoeCMS(-secCMS.X(), -secCMS.Y(), -secCMS.Z(), secCMS.E());
78 ROOT::Math::PxPyPzEVector sec4roe = T.cmsToLab(secRoeCMS);
79
80 // update sec3v direction:
81 sec3v.SetXYZ(sec4roe.X(), sec4roe.Y(), sec4roe.Z());
82 }
83
84
85 B2Vector3D cross = tag3v.Unit().Cross(sec3v.Unit());
86 double dot = tag3v.Unit().Dot(sec3v.Unit());
87
88 // Rotation to make secondary B point as tag B
89 rot.Rotate(-acos(dot), cross);
90
91 // Closure test that rotation does what expected:
92 B2Vector3D test = rot * sec3v;
93 double smallValue = 1e-12;
94 if ((abs(sin(test.Phi() - tag3v.Phi())) > smallValue) or (abs(test.Theta() - tag3v.Theta()) > smallValue)) {
95 B2ERROR("Loss of accuracy during rotation" << LogVar("Delta phi", abs(sin(test.Phi() - tag3v.Phi())))
96 << LogVar("Delta Theta", abs(test.Theta() - tag3v.Theta())));
97 }
98 } else {
99 B2ERROR("No momentum information provided for the tag/simulated particle list, can not update tracks");
100 }
101 return rot;
102}
103
105{
106 if (m_mixing) {
107 // get beam vertex for P2:
108 if (m_eventExtraInfo->hasExtraInfo("IPX")
109 and m_eventExtraInfo->hasExtraInfo("IPY")
110 and m_eventExtraInfo->hasExtraInfo("IPZ")) {
111 double xv2 = m_eventExtraInfo->getExtraInfo("IPX");
112 double yv2 = m_eventExtraInfo->getExtraInfo("IPY");
113 double zv2 = m_eventExtraInfo->getExtraInfo("IPZ");
114 const B2Vector3D origSpot(xv2, yv2, zv2);
115
116 // Now vertex from DB:
117 static DBObjPtr<Belle2::BeamSpot> beamSpotDB;
118 const B2Vector3D beamSpot = beamSpotDB->getIPPosition();
119
120 const TRotation rot = tag_vertex_rotation();
121 const double bz = BFieldManager::getFieldInTesla(beamSpot).Z();
122
123 // Loop over track fit results from the attached part of the event:
124 // Loop over new tracks and corresponding track fit results
125 for (int idxTr = m_mergedArrayIndices->getExtraInfo("Tracks"); idxTr < m_tracks.getEntries(); idxTr++) {
126 for (short int i : m_tracks[idxTr]->getValidIndices()) {
127 auto t_idx = m_tracks[idxTr]->m_trackFitIndices[i];
128
129 short charge = m_trackFits[t_idx]->getChargeSign();
130 auto helixO = m_trackFits[t_idx]->getHelix();
131 // Move track such that IP becomes centered at the beamSpot
132 helixO.passiveMoveBy(origSpot - beamSpot);
133
134 // Also Rotate:
135 B2Vector3D position = helixO.getPerigee();
136 B2Vector3D momentum = rot * B2Vector3D(helixO.getMomentum(bz));
137
138 // New helix
139 // Helix helix(position, momentum, charge, bz);
140 Helix helix(ROOT::Math::XYZVector(position.X(), position.Y(), position.Z()),
141 ROOT::Math::XYZVector(momentum.X(), momentum.Y(), momentum.Z()), charge, bz);
142
143 // Store back in the mdst:
144 m_trackFits[t_idx]->m_tau[TrackFitResult::iD0] = helix.getD0();
145 m_trackFits[t_idx]->m_tau[TrackFitResult::iPhi0] = helix.getPhi0();
146 m_trackFits[t_idx]->m_tau[TrackFitResult::iOmega] = helix.getOmega();
147 m_trackFits[t_idx]->m_tau[TrackFitResult::iZ0] = helix.getZ0();
148 m_trackFits[t_idx]->m_tau[TrackFitResult::iTanLambda] = helix.getTanLambda();
149
150 }
151 }
152 // also ECL clusters:
153 cluster_rotation(rot);
154
155 } else {
156 B2ERROR("No vertex info, can not update tracks");
157 }
158
159 } else {
160 if (
161 m_eventExtraInfo_orig->hasExtraInfo("X")
162 and m_eventExtraInfo_orig->hasExtraInfo("Y")
163 and m_eventExtraInfo_orig->hasExtraInfo("Z")
164 and m_eventExtraInfo->hasExtraInfo("X")
165 and m_eventExtraInfo->hasExtraInfo("Y")
166 and m_eventExtraInfo->hasExtraInfo("Z")
167 ) {
168
169 B2Vector3D vertexTag(m_eventExtraInfo_orig->getExtraInfo("X"),
170 m_eventExtraInfo_orig->getExtraInfo("Y"),
171 m_eventExtraInfo_orig->getExtraInfo("Z"));
172
173 B2Vector3D vertexEmb(m_eventExtraInfo->getExtraInfo("X"),
174 m_eventExtraInfo->getExtraInfo("Y"),
175 m_eventExtraInfo->getExtraInfo("Z"));
176
177 const double bz = BFieldManager::getFieldInTesla(vertexTag).Z();
178 const TRotation rot = tag_vertex_rotation();
179
180 // Loop over new tracks and corresponding track fit results
181 for (int idxTr = m_mergedArrayIndices->getExtraInfo("Tracks"); idxTr < m_tracks.getEntries(); idxTr++) {
182 for (short int i : m_tracks[idxTr]->getValidIndices()) {
183 auto t_idx = m_tracks[idxTr]->m_trackFitIndices[i];
184
185 // get d0, z0 vs original simulated-truth vertex. They include smearing due to reconstruction.
186 auto helix = m_trackFits[t_idx]->getHelix();
187 helix.passiveMoveBy(vertexEmb);
188
189 B2Vector3D mom = m_trackFits[t_idx]->getMomentum();
190 short charge = m_trackFits[t_idx]->getChargeSign();
191
192 // Rotate (no boost for now)
193 B2Vector3D momTag = rot * mom;
194
195 // Define new helix "h", based on tag vertex position and rotated track momentum. Note that the vertex position is usually well
196 // reconstructed and smearing in the track position parameters (d0,z0) for the helix h is not sufficient. In addition,
197 // for embedding channels with multiple tracks we need an extra smearing for each track individually. To take into account correlations,
198 // at least to first order, we used determined above (d0,z0) parameters from the track vs original simulated vertex.
199
200 Helix h(vertexTag, momTag, charge, bz);
201
202 m_trackFits[t_idx]->m_tau[TrackFitResult::iD0] = h.getD0() + helix.getD0(); // include smearing simulated -> reconstructed
203 m_trackFits[t_idx]->m_tau[TrackFitResult::iPhi0] = h.getPhi0();
204 m_trackFits[t_idx]->m_tau[TrackFitResult::iZ0] = h.getZ0() + helix.getZ0(); // include smearing simulated -> reconstructed
205 m_trackFits[t_idx]->m_tau[TrackFitResult::iTanLambda] = h.getTanLambda();
206 m_trackFits[t_idx]->m_tau[TrackFitResult::iOmega] = h.getOmega();
207
208 }
209 }
210 cluster_rotation(rot);
211 }
212
213 else {
214 B2ERROR("No track parameters info, can not update tracks");
215 }
216 }
217
218}
219
220
222{
223 // Loop over added clusters:
224 for (int idxCl = m_mergedArrayIndices->getExtraInfo("ECLClusters"); idxCl < m_eclclusters.getEntries(); idxCl++) {
225 B2Vector3D pos = m_eclclusters[idxCl]->getClusterPosition();
226 B2Vector3D newPos = rot * pos;
227 // Keep same R, update theta/phi:
228 m_eclclusters[idxCl]->setTheta(newPos.Theta());
229 m_eclclusters[idxCl]->setPhi(newPos.Phi());
230 }
231}
R E
internal precision of FFTW codelets
DataType Phi() const
The azimuth angle.
Definition: B2Vector3.h:151
DataType Z() const
access variable Z (= .at(2) without boundary check)
Definition: B2Vector3.h:435
DataType Theta() const
The polar angle.
Definition: B2Vector3.h:153
B2Vector3< DataType > Cross(const B2Vector3< DataType > &p) const
Cross product.
Definition: B2Vector3.h:296
DataType X() const
access variable X (= .at(0) without boundary check)
Definition: B2Vector3.h:431
DataType Y() const
access variable Y (= .at(1) without boundary check)
Definition: B2Vector3.h:433
DataType Mag2() const
The magnitude squared (rho^2 in spherical coordinate system).
Definition: B2Vector3.h:157
DataType Dot(const B2Vector3< DataType > &p) const
Scalar product.
Definition: B2Vector3.h:290
B2Vector3< DataType > Unit() const
Unit vector parallel to this.
Definition: B2Vector3.h:269
void SetXYZ(DataType x, DataType y, DataType z)
set all coordinates using data type
Definition: B2Vector3.h:464
static ROOT::Math::XYZVector getFieldInTesla(const ROOT::Math::XYZVector &pos)
return the magnetic field at a given position in Tesla.
Definition: BFieldManager.h:61
Helix parameter class.
Definition: Helix.h:48
Class for accessing objects in the database.
Definition: DBObjPtr.h:21
Base class for Modules.
Definition: Module.h:72
void setDescription(const std::string &description)
Sets the description of the module.
Definition: Module.cc:214
Class to hold Lorentz transformations from/to CMS and boost vector.
static ROOT::Math::PxPyPzMVector labToCms(const ROOT::Math::PxPyPzMVector &vec)
Transforms Lorentz vector into CM System.
static ROOT::Math::PxPyPzMVector cmsToLab(const ROOT::Math::PxPyPzMVector &vec)
Transforms Lorentz vector into Laboratory System.
StoreObjPtr< EventExtraInfo > m_eventExtraInfo_orig
Event extra info original.
TRotation tag_vertex_rotation()
Helper function to determine rotation matrix.
virtual void initialize() override
Initialize the Module.
virtual void event() override
Event processor.
StoreArray< Track > m_tracks
tracks
void cluster_rotation(const TRotation &rot)
Rotate clusters.
StoreArray< TrackFitResult > m_trackFits
track fits
StoreObjPtr< EventExtraInfo > m_mergedArrayIndices
indices where the StoreArrays were merged
StoreObjPtr< EventExtraInfo > m_eventExtraInfo
Event extra info.
StoreArray< ECLCluster > m_eclclusters
StoreArray of ECLCluster.
bool m_mixing
Fix to common vertex.
static const unsigned int iZ0
Index for z0.
static const unsigned int iTanLambda
Index tan lambda.
static const unsigned int iD0
Index for d0.
static const unsigned int iOmega
Index for omega.
static const unsigned int iPhi0
Index for phi0.
Class to store variables with their name which were sent to the logging service.
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
B2Vector3< double > B2Vector3D
typedef for common usage with double
Definition: B2Vector3.h:516
double sqrt(double a)
sqrt for double
Definition: beamHelpers.h:28
T dot(GeneralVector< T > a, GeneralVector< T > b)
dot product of two general vectors
Definition: beamHelpers.h:163
Abstract base class for different kinds of events.