Belle II Software development
initialparticles.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 <framework/datastore/DataStore.h>
10#include <framework/database/DBStore.h>
11#include <framework/dbobjects/BeamParameters.h>
12#include <framework/utilities/CalcMeanCov.h>
13#include <generators/utilities/InitialParticleGeneration.h>
14
15#include <gtest/gtest.h>
16
17using namespace std;
18using namespace Belle2;
19
20namespace {
21
24 class InitialParticleGenerationTests : public ::testing::Test {
25 protected:
26
28 virtual void SetUp()
29 {
31 generator.initialize();
33
34 // have some useful defaults for the beam parameters
35 beamparams.setHER(7.004, 0.0415, 0, {2.63169e-05, 1e-5, 1e-5});
36 beamparams.setLER(4.002, -0.0415, 0, {5.64063e-06, 1e-5, 1e-5});
37 beamparams.setVertex({0, 1, 2}, {4.10916e-07, 0, -2.64802e-06, 0, 1.7405e-11, 0, -2.64802e-06, 0, 0.000237962});
38 }
39
41 virtual void TearDown()
42 {
45 }
46
47 InitialParticleGeneration generator{BeamParameters::c_smearALL};
48 BeamParameters beamparams;
49 };
50
52 TEST_F(InitialParticleGenerationTests, TestCMSGeneration)
53 {
54 beamparams.setGenerationFlags(BeamParameters::c_generateCMS);
55 DBStore::Instance().addConstantOverride("BeamParameters", new BeamParameters(beamparams));
56 auto initialCMS = generator.generate();
57 // transformation should be identity
58 EXPECT_EQ(initialCMS.getLabToCMS(), ROOT::Math::LorentzRotation());
59 // her should be along z
60 EXPECT_NEAR(initialCMS.getHER().Theta(), 0, 1e-15);
61 // ler should be opposite z
62 EXPECT_NEAR(initialCMS.getLER().Theta(), M_PI, 1e-15);
63 // both should have the same energy
64 EXPECT_NEAR(initialCMS.getHER().E(), initialCMS.getLER().E(), 1e-15);
65 // and the invariant mass should of course be correct
66 EXPECT_EQ(initialCMS.getMass(), beamparams.getMass());
67
68 // and now compare it to generation in Lab
69 beamparams.setGenerationFlags(0);
70 DBStore::Instance().addConstantOverride("BeamParameters", new BeamParameters(beamparams));
71 auto initialLAB = generator.generate();
72 // same invariant mass
73 EXPECT_EQ(initialLAB.getMass(), beamparams.getMass());
74 // no smearing so LER and HER need to be identical to beam parameters
75 EXPECT_EQ(initialLAB.getHER(), beamparams.getHER());
76 EXPECT_EQ(initialLAB.getLER(), beamparams.getLER());
77 // so check that the CMS beams are identical to the transformed lab ones
78 EXPECT_EQ(initialCMS.getHER(), initialLAB.getLabToCMS() * initialLAB.getHER());
79 EXPECT_EQ(initialCMS.getLER(), initialLAB.getLabToCMS() * initialLAB.getLER());
80 }
81
83 TEST_F(InitialParticleGenerationTests, TestEnergySmear)
84 {
85 // two beams completely head on, one with energy uncertainty so invariant
86 // mass uncertainty should be exactly the same as single uncertainty. Here
87 // we give variance so we expect 0.1
88 beamparams.setHER(10, 0, 0, {0.01});
89 beamparams.setLER(10, M_PI, 0, {0});
90 beamparams.setGenerationFlags(BeamParameters::c_smearBeamEnergy);
91 DBStore::Instance().addConstantOverride("BeamParameters", new BeamParameters(beamparams));
92
93 // so let's generate events with this and store all invariant masses
94 {
95 CalcMeanCov<1> mean;
96 for (int i = 0; i < 100000; ++i) {
97 auto& initial = generator.generate();
98 ASSERT_TRUE(initial.hasGenerationFlags(BeamParameters::c_smearBeamEnergy));
99 mean.add(initial.getMass());
100 }
101 // and compare with expectation
102 EXPECT_NEAR(mean.getStddev(), 0.1, 0.0005);
103 EXPECT_NEAR(mean.getMean(), 20, 0.001);
104 }
105
106 // uncertainty on both so result should be sqrt(a^2 + b^2) = sqrt(2) * 0.1
107 beamparams.setLER(10, M_PI, 0, {0.01});
108 beamparams.setGenerationFlags(BeamParameters::c_smearBeamEnergy);
109 DBStore::Instance().addConstantOverride("BeamParameters", new BeamParameters(beamparams));
110 {
111 CalcMeanCov<1> mean;
112 for (int i = 0; i < 100000; ++i) {
113 auto& initial = generator.generate();
114 ASSERT_TRUE(initial.hasGenerationFlags(BeamParameters::c_smearBeamEnergy));
115 mean.add(initial.getMass());
116 }
117 EXPECT_NEAR(mean.getStddev(), std::sqrt(2) * 0.1, 0.0005);
118 EXPECT_NEAR(mean.getMean(), 20, 0.001);
119 }
120 }
121
122
126 TEST_F(InitialParticleGenerationTests, TestVertexSmear)
127 {
128 beamparams.setGenerationFlags(BeamParameters::c_smearVertex);
129 DBStore::Instance().addConstantOverride("BeamParameters", new BeamParameters(beamparams));
130
131 CalcMeanCov<3> mean;
132 for (int i = 0; i < 100000; ++i) {
133 auto& initial = generator.generate();
134 mean.add(initial.getVertex().X(), initial.getVertex().Y(), initial.getVertex().Z());
135 }
136 auto cov = beamparams.getCovVertex();
137 auto pos = beamparams.getVertex();
138 EXPECT_NEAR(mean.getMean(0), pos.x(), 1e-4);
139 EXPECT_NEAR(mean.getMean(1), pos.y(), 1e-4);
140 EXPECT_NEAR(mean.getMean(2), pos.z(), 1e-4);
141 for (int i = 0; i < 3; ++i) {
142 for (int j = 0; j < 3; ++j) {
143 EXPECT_NEAR(mean.getCovariance(i, j), cov(i, j), 1e-6);
144 }
145 }
146 }
147
156 TEST_F(InitialParticleGenerationTests, TestFlags)
157 {
158 // so loop over all flags
159 for (int flag = 0; flag <= BeamParameters::c_smearALL; ++flag) {
160 // set the flag and overwrite dbstore
161 beamparams.setGenerationFlags(flag);
162 DBStore::Instance().addConstantOverride("BeamParameters", new BeamParameters(beamparams));
163 // rememeber last event and set it to the settings for initialization
164 MCInitialParticles last = beamparams;
165 // no generate a few events and check everything
166 for (int i = 0; i < 5; ++i) {
167 auto& initial = generator.generate();
168 EXPECT_EQ(flag, initial.getGenerationFlags());
169 // create text representation of flags
170 const std::string flags = initial.getGenerationFlagString();
171 if (flag & BeamParameters::c_smearBeam) {
172 // smearing of beam is active, check that the beams are actually
173 // different to the settings and the previous event
174 EXPECT_NE(initial.getHER(), beamparams.getHER()) << flags << " " << i;
175 EXPECT_NE(initial.getLER(), beamparams.getLER()) << flags << " " << i;
176 EXPECT_NE(initial.getHER(), last.getHER()) << flags << " " << i;
177 EXPECT_NE(initial.getLER(), last.getLER()) << flags << " " << i;
178 } else if (!(flag & BeamParameters::c_generateCMS)) {
179 // no smearing no cms generation, so everything should stay fixed.
180 EXPECT_EQ(initial.getHER(), beamparams.getHER()) << flags << " " << i;
181 EXPECT_EQ(initial.getLER(), beamparams.getLER()) << flags << " " << i;
182 EXPECT_EQ(initial.getHER(), last.getHER()) << flags << " " << i;
183 EXPECT_EQ(initial.getLER(), last.getLER()) << flags << " " << i;
184 } else {
185 // we want to compare CMS initial particles to lab beam energies
186 // but transformation is identity if c_generateCMS is set. Reset
187 // it so that the can boost beams to CMS for comparison
188 beamparams.setGenerationFlags(0);
189 EXPECT_EQ(initial.getHER(), beamparams.getLabToCMS() * beamparams.getHER()) << flags << " " << i;
190 EXPECT_EQ(initial.getLER(), beamparams.getLabToCMS() * beamparams.getLER()) << flags << " " << i;
191 // comparison to beamparameters fails in generateCMS so we just
192 // skip the first round here
193 if (i > 0) {
194 EXPECT_EQ(initial.getHER(), last.getHER()) << flags << " " << i;
195 EXPECT_EQ(initial.getLER(), last.getLER()) << flags << " " << i;
196 }
197 }
198 if (flag & BeamParameters::c_smearVertex) {
199 //smearing of the vertex is enabled, make sure the vertex changes
200 EXPECT_NE(initial.getVertex(), beamparams.getVertex());
201 EXPECT_NE(initial.getVertex(), last.getVertex());
202 } else {
203 //otherwise make sure it doesn't change.
204 EXPECT_EQ(initial.getVertex(), beamparams.getVertex());
205 EXPECT_EQ(initial.getVertex(), last.getVertex());
206 }
207 last = initial;
208 }
209 }
210 }
211
213 TEST_F(InitialParticleGenerationTests, TestValidFlag)
214 {
215 beamparams.setGenerationFlags(0);
216 DBStore::Instance().addConstantOverride("BeamParameters", new BeamParameters(beamparams));
217
218 MCInitialParticles& initial = generator.generate();
219 ROOT::Math::PxPyPzEVector her = initial.getHER();
220 ROOT::Math::PxPyPzEVector ler = initial.getLER();
221 ROOT::Math::XYZVector vertex = initial.getVertex();
222 for (int i = 0; i < 10; ++i) {
223 initial = generator.generate();
224 EXPECT_EQ(her, initial.getHER());
225 EXPECT_EQ(ler, initial.getLER());
226 EXPECT_EQ(vertex, initial.getVertex());
227 }
228 beamparams.setGenerationFlags(BeamParameters::c_smearALL);
229 DBStore::Instance().addConstantOverride("BeamParameters", new BeamParameters(beamparams));
230 for (int i = 0; i < 10; ++i) {
231 initial = generator.generate();
232 EXPECT_NE(her, initial.getHER());
233 EXPECT_NE(ler, initial.getLER());
234 EXPECT_NE(vertex, initial.getVertex());
235 her = initial.getHER();
236 ler = initial.getLER();
237 vertex = initial.getVertex();
238 }
239 }
240
241 TEST_F(InitialParticleGenerationTests, UpdateVertex)
242 {
243 beamparams.setGenerationFlags(BeamParameters::c_smearBeam);
244 DBStore::Instance().addConstantOverride("BeamParameters", new BeamParameters(beamparams));
245 // first run but no smearing allowed, should return the nominal vertex
246 ROOT::Math::XYZVector shift = generator.updateVertex();
247 EXPECT_EQ(shift, ROOT::Math::XYZVector(0, 1, 2));
248 // create a new initial particle. Particle exists now, no smearing allowed so no change in shift
249 const MCInitialParticles& initial = generator.generate();
250 auto nominal = initial.getVertex();
251 shift = generator.updateVertex();
252 EXPECT_EQ(shift, ROOT::Math::XYZVector(0, 0, 0));
253 // ok, allow smearing, now we expect shift
254 beamparams.setGenerationFlags(BeamParameters::c_smearALL);
255 DBStore::Instance().addConstantOverride("BeamParameters", new BeamParameters(beamparams));
256 shift = generator.updateVertex();
257 EXPECT_NE(shift, ROOT::Math::XYZVector(0, 0, 0));
258 EXPECT_EQ(nominal + shift, initial.getVertex());
259 // but running again should not shift again
260 shift = generator.updateVertex();
261 EXPECT_EQ(shift, ROOT::Math::XYZVector(0, 0, 0));
262 // unless we force regeneration
263 auto previous = initial.getVertex();
264 shift = generator.updateVertex(true);
265 EXPECT_NE(shift, ROOT::Math::XYZVector(0, 0, 0));
266 EXPECT_EQ(previous + shift, initial.getVertex());
267 }
268}
This class contains the nominal beam parameters and the parameters used for smearing of the primary v...
Class to calculate mean and and covariance between a number of parameters on running data without sto...
Definition: CalcMeanCov.h:35
static DataStore & Instance()
Instance of singleton Store.
Definition: DataStore.cc:54
void setInitializeActive(bool active)
Setter for m_initializeActive.
Definition: DataStore.cc:94
void reset(EDurability durability)
Frees memory occupied by data store items and removes all objects from the map.
Definition: DataStore.cc:86
This class contains the initial state for the given event.
const ROOT::Math::PxPyPzEVector & getHER() const
Get 4vector of the high energy beam.
const ROOT::Math::PxPyPzEVector & getLER() const
Get 4vector of the low energy beam.
const ROOT::Math::XYZVector & getVertex() const
Get the position of the collision.
void reset(bool keepEntries=false)
Invalidate all payloads.
Definition: DBStore.cc:177
static DBStore & Instance()
Instance of a singleton DBStore.
Definition: DBStore.cc:28
void addConstantOverride(const std::string &name, TObject *obj, bool oneRun=false)
Add constant override payload.
Definition: DBStore.cc:204
Abstract base class for different kinds of events.
STL namespace.