Belle II Software  release-08-01-10
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 
17 using namespace Belle2;
18 
19 //-----------------------------------------------------------------
20 // Register module
21 //-----------------------------------------------------------------
22 REG_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 cros = 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), cros);
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
B2Vector3< DataType > Cross(const B2Vector3< DataType > &p) const
Cross product.
Definition: B2Vector3.h:296
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
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
B2Vector3< DataType > Unit() const
Unit vector parallel to this.
Definition: B2Vector3.h:269
DataType Dot(const B2Vector3< DataType > &p) const
Scalar product.
Definition: B2Vector3.h:290
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
const TVector3 & getIPPosition() const
Get the IP position.
Definition: BeamSpot.h:66
Helix parameter class.
Definition: Helix.h:48
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.
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
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.