Belle II Software  release-08-01-10
BelleMCOutputModule.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 <b2bii/modules/BelleMCOutput/BelleMCOutputModule.h>
11 
12 /* Basf2 headers. */
13 #include <framework/gearbox/Unit.h>
14 #include <framework/logging/Logger.h>
15 
16 /* Belle headers. */
17 #include <belle_legacy/tables/belletdf.h>
18 #include <belle_legacy/tables/hepevt.h>
19 #include <belle_legacy/tables/filespec.h>
20 
21 /* ROOT headers. */
22 #include <TMatrixD.h>
23 #include <Math/RotationY.h>
24 #include <Math/Rotation3D.h>
25 
26 using namespace Belle2;
27 
28 REG_MODULE(BelleMCOutput);
29 
31  Module()
32 {
33  setDescription("Output of MC particle list in Belle format.");
35  addParam("outputFileName", m_OutputFileName,
36  "Output file name.", std::string("belle_mc.mdst"));
37  addParam("decayKsInGenerator", m_DecayKsInGenerator,
38  "Decay K_S0 in generator.", false);
39  addParam("decayLambdaInGenerator", m_DecayLambdaInGenerator,
40  "Decay Lambda in generator.", false);
41 }
42 
44 {
45 }
46 
48 {
49  m_BelleFile = new Belle::Panther_FileIO(m_OutputFileName.c_str(), BBS_WRITE);
50  m_BelleFile->write(BBS_FORMAT, 0);
51  m_BelleFile->save_br("BELLE_FILE_SPECIFICATION");
52  m_BelleFile->save_br("BELLE_RUNHEAD");
53  m_BelleFile->save_br("BELLE_NOMINAL_BEAM");
54  m_BelleFile->save("GEN_HEPEVT");
55  B2WARNING(
56  "************ ATTENTION! ************\n"
57  "\n"
58  " Belle MC generation differs from Belle II. In order to generate MC "
59  "correctly, you must do the following:\n"
60  "\n"
61  " 1. Use global tag with smearing of beam parameters and generation "
62  "flags: b2bii_beamParameters_with_smearing (there are no smearing data "
63  "or generation flags in the tags B2BII or B2BII_MC).\n"
64  " 2. Disable smearing in Belle simulation by removing the module "
65  "\"bpsmear\" from basf gsim scripts.\n"
66  "\n"
67  "It is also necessary to consider the following differences:\n"
68  "\n"
69  " 1. When converting the simulation result back to Belle II format, "
70  "it is recommended to disable conversion of beam parameters "
71  "(convertBeamParameters = False). Since the format of the table "
72  "BELLE_NOMINAL_BEAM is not sufficient to store an arbitrary covariance "
73  "matrix, the covariance matrix of IP position (BeamSpot) is not guaranteed "
74  "to be exactly the same after conversion.\n"
75  " 2. By default, decays of long-lived particles are removed and particles "
76  "are declared to be stable in generator (ISTHEP == 1 in basf) because "
77  "such decays are simulated by GEANT3 in basf. However, you may choose "
78  "to decay such particles via module parameters. This results in direct "
79  "passing of the decay products to simulation, i.e. material effects are "
80  "ignored. In this case, you may need to perform an additional study "
81  "of the difference between data and MC.\n"
82  "\n"
83  "************************************\n"
84  );
85 }
86 
88 {
89  Belle::Belle_file_specification_Manager& fileManager =
90  Belle::Belle_file_specification_Manager::get_manager();
91  fileManager.remove();
92  int position = 0;
93  int length = m_OutputFileName.size();
94  do {
95  Belle::Belle_file_specification& file = fileManager.add();
96  file.Spec(m_OutputFileName.substr(position, std::min(length, 8)).c_str());
97  position += 8;
98  length -= 8;
99  } while (length > 0);
100  Belle::Belle_runhead_Manager& runheadManager =
101  Belle::Belle_runhead_Manager::get_manager();
102  runheadManager.remove();
103  Belle::Belle_runhead& runhead = runheadManager.add();
104  runhead.ExpMC(2);
105  runhead.ExpNo(m_EventMetaData->getExperiment());
106  runhead.RunNo(m_EventMetaData->getRun());
107  runhead.Time(time(nullptr));
108  runhead.Type(0);
109  ROOT::Math::PxPyPzEVector momentumLER = m_BeamParameters->getLER();
110  ROOT::Math::PxPyPzEVector momentumHER = m_BeamParameters->getHER();
111  runhead.ELER(momentumLER.E());
112  runhead.EHER(momentumHER.E());
113  Belle::Belle_nominal_beam_Manager& beamManager =
114  Belle::Belle_nominal_beam_Manager::get_manager();
115  beamManager.remove();
116  Belle::Belle_nominal_beam& beam = beamManager.add();
117  beam.px_high(momentumHER.X());
118  beam.py_high(momentumHER.Y());
119  beam.pz_high(momentumHER.Z());
120  beam.px_low(momentumLER.X());
121  beam.py_low(momentumLER.Y());
122  beam.pz_low(momentumLER.Z());
123  TMatrixDSym herCovariance = m_BeamParameters->getCovHER();
124  beam.sigma_p_high(sqrt(herCovariance[0][0]));
125  TMatrixDSym lerCovariance = m_BeamParameters->getCovLER();
126  beam.sigma_p_low(sqrt(lerCovariance[0][0]));
127  /*
128  * The vertex parameters are in cm, as in basf2.
129  * The unit is not the same as for particles in GEN_HEPEVT.
130  */
131  ROOT::Math::XYZVector vertex = m_BeamParameters->getVertex();
132  beam.ip_x(vertex.X());
133  beam.ip_y(vertex.Y());
134  beam.ip_z(vertex.Z());
135  TMatrixDSym vertexCovariance = m_BeamParameters->getCovVertex();
136  beam.cang_high(momentumHER.Theta());
137  beam.cang_low(M_PI - momentumLER.Theta());
138  double angleIPZX = momentumHER.Theta() / 2;
139  beam.angle_ip_zx(angleIPZX);
140  /*
141  * Transformation of error matrix. It is inverse to the transformation in
142  * belle_legacy/ip/IpProfile.cc.
143  */
144  ROOT::Math::RotationY rotationY(-angleIPZX);
145  ROOT::Math::Rotation3D rotation(rotationY);
146  TMatrixD rotationMatrix(3, 3);
147  rotation.GetRotationMatrix(rotationMatrix);
148  TMatrixDSym vertexCovariance2 = vertexCovariance.Similarity(rotationMatrix);
149  beam.sigma_ip_x(sqrt(vertexCovariance2[0][0]));
150  beam.sigma_ip_y(sqrt(vertexCovariance2[1][1]));
151  beam.sigma_ip_z(sqrt(vertexCovariance2[2][2]));
152  m_BelleFile->write(BBS_BEGIN_RUN, 0);
153 }
154 
156  const MCParticle* particle, MCParticleGraph::GraphParticle* mother)
157 {
159  part = *particle;
160  if (mother != nullptr)
161  part.comesFrom(*mother);
162  int pdg = abs(particle->getPDG());
163  if ((pdg == Const::muon.getPDGCode()) ||
164  (pdg == Const::pion.getPDGCode()) ||
165  (pdg == Const::kaon.getPDGCode()) ||
166  ((pdg == Const::Kshort.getPDGCode()) && !m_DecayKsInGenerator) ||
167  (pdg == Const::Klong.getPDGCode()) ||
168  (pdg == Const::neutron.getPDGCode()) ||
169  ((pdg == Const::Lambda.getPDGCode()) && !m_DecayLambdaInGenerator) ||
170  (pdg == 3222) || // Sigma+
171  (pdg == 3112) || // Sigma-
172  (pdg == 3322) || // Xi0
173  (pdg == 3312) || // Xi-
174  (pdg == 3334)) { // Omega-
175  part.addStatus(MCParticle::c_StableInGenerator);
176  return;
177  }
178  std::vector<MCParticle*> daughters = particle->getDaughters();
179  for (const MCParticle* daughter : daughters)
180  addParticle(daughter, &part);
181 }
182 
184 {
185  Belle::Gen_hepevt_Manager& hepevtManager =
186  Belle::Gen_hepevt_Manager::get_manager();
187  hepevtManager.remove();
188  /*
189  * The time shift applied by basf module "evtgen" (file beam.cc) is
190  * vertex z coordinate [mm] / (2.0 * 2.99792458).
191  * The vertex coordinate is calculated relative to the IP position.
192  * The position correction happens at the simulation stage (bpsmear) in basf.
193  */
194  double timeShift = (m_MCInitialParticles->getVertex().Z() -
195  m_BeamParameters->getVertex().Z()) /
196  Unit::mm / (2.0 * 0.1 * Const::speedOfLight);
197  /*
198  * Regeneration of MCParticle array. It is necesary because in basf the
199  * long-lived particles (K_S0, K_L0, Lambda, neutron, pi, K, mu)
200  * are decayed by GEANT3.
201  */
203  for (const MCParticle& particle : m_MCParticles) {
204  if (particle.getMother() == nullptr)
205  addParticle(&particle, nullptr);
206  }
210  for (const MCParticle& particle : m_MCParticles) {
211  Belle::Gen_hepevt& hepevt = hepevtManager.add();
212  if (particle.hasStatus(MCParticle::c_Initial))
213  hepevt.isthep(3);
214  else if (particle.hasStatus(MCParticle::c_StableInGenerator))
215  hepevt.isthep(1);
216  else
217  hepevt.isthep(2);
218  hepevt.idhep(particle.getPDG());
219  hepevt.reset_mother();
220  const MCParticle* mother = particle.getMother();
221  int motherIndex = 0;
222  if (mother != nullptr)
223  motherIndex = mother->getIndex();
224  hepevt.moFirst(motherIndex);
225  hepevt.moLast(motherIndex);
226  hepevt.daFirst(particle.getFirstDaughter());
227  hepevt.daLast(particle.getLastDaughter());
228  ROOT::Math::PxPyPzEVector momentum = particle.get4Vector();
229  hepevt.PX(momentum.Px());
230  hepevt.PY(momentum.Py());
231  hepevt.PZ(momentum.Pz());
232  hepevt.E(momentum.E());
233  hepevt.M(particle.getMass());
234  ROOT::Math::XYZVector vertex = particle.getVertex();
235  hepevt.VX(vertex.X() / Unit::mm);
236  hepevt.VY(vertex.Y() / Unit::mm);
237  hepevt.VZ(vertex.Z() / Unit::mm);
238  hepevt.T(particle.getProductionTime() / Unit::mm * Const::speedOfLight +
239  timeShift);
240  }
241  m_BelleFile->write(BBS_EVENT, m_EventMetaData->getEvent());
242 }
243 
245 {
246 }
247 
249 {
250  delete m_BelleFile;
251 }
void addParticle(const MCParticle *particle, MCParticleGraph::GraphParticle *mother)
Add particle to graph.
StoreObjPtr< MCInitialParticles > m_MCInitialParticles
Initial particles.
virtual void initialize() override
Initializer.
bool m_DecayKsInGenerator
Decay K_S0 in generator.
virtual void event() override
This method is called for each event.
Belle::Panther_FileIO * m_BelleFile
Belle file input-output handler.
virtual void endRun() override
This method is called if the current run ends.
virtual void terminate() override
This method is called at the end of the event processing.
virtual void beginRun() override
Called when entering a new run.
DBObjPtr< BeamParameters > m_BeamParameters
Beam parameters.
virtual ~BelleMCOutputModule()
Destructor.
bool m_DecayLambdaInGenerator
Decay Lambda in generator.
std::string m_OutputFileName
Output file name.
StoreObjPtr< EventMetaData > m_EventMetaData
Event metadata.
StoreArray< MCParticle > m_MCParticles
MC particles.
MCParticleGraph m_MCParticleGraph
MC particle graph.
static const ParticleType neutron
neutron particle
Definition: Const.h:666
static const ParticleType Lambda
Lambda particle.
Definition: Const.h:670
static const ChargedStable muon
muon particle
Definition: Const.h:651
static const ChargedStable pion
charged pion particle
Definition: Const.h:652
static const ParticleType Klong
K^0_L particle.
Definition: Const.h:669
static const double speedOfLight
[cm/ns]
Definition: Const.h:686
static const ParticleType Kshort
K^0_S particle.
Definition: Const.h:668
static const ChargedStable kaon
charged kaon particle
Definition: Const.h:653
Class to represent Particle data in graph.
@ c_checkCyclic
Check for cyclic dependencies.
@ c_clearParticles
Clear the particle list before adding the graph.
@ c_setDecayInfo
Set decay time and vertex.
void generateList(const std::string &name="", int options=c_setNothing)
Generates the MCParticle list and stores it in the StoreArray with the given name.
A Class to store the Monte Carlo particle information.
Definition: MCParticle.h:32
@ c_Initial
bit 5: Particle is initial such as e+ or e- and not going to Geant4
Definition: MCParticle.h:57
@ c_StableInGenerator
bit 1: Particle is stable, i.e., not decaying in the generator.
Definition: MCParticle.h:49
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_Output
This module is an output module (writes data).
Definition: Module.h:79
static const double mm
[millimeters]
Definition: Unit.h:70
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
double sqrt(double a)
sqrt for double
Definition: beamHelpers.h:28
void clear()
Reset particles and decay information to make the class reusable.
GraphParticle & addParticle()
Add new particle to the graph.
Abstract base class for different kinds of events.