Belle II Software  release-08-01-10
PXDBackgroundModule.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 #include <pxd/modules/pxdBackground/PXDBackgroundModule.h>
9 
10 #include <framework/datastore/DataStore.h>
11 #include <framework/datastore/StoreObjPtr.h>
12 #include <framework/datastore/StoreArray.h>
13 #include <framework/datastore/RelationArray.h>
14 
15 #include <framework/dataobjects/FileMetaData.h>
16 #include <framework/dataobjects/BackgroundMetaData.h>
17 #include <framework/gearbox/Const.h>
18 #include <mdst/dataobjects/MCParticle.h>
19 #include <pxd/dataobjects/PXDSimHit.h>
20 #include <pxd/dataobjects/PXDTrueHit.h>
21 #include <pxd/dataobjects/PXDDigit.h>
22 #include <pxd/dataobjects/PXDCluster.h>
23 #include <pxd/dataobjects/PXDEnergyDepositionEvent.h>
24 #include <pxd/dataobjects/PXDNeutronFluxEvent.h>
25 #include <pxd/dataobjects/PXDOccupancyEvent.h>
26 #include <cmath>
27 #include <fstream>
28 #include <boost/format.hpp>
29 
30 #include "TVector3.h"
31 
32 using namespace std;
33 using boost::format;
34 using namespace Belle2;
35 using namespace Belle2::PXD;
36 
37 
38 
39 //-----------------------------------------------------------------
40 // Register the Module
41 //-----------------------------------------------------------------
42 REG_MODULE(PXDBackground);
43 
44 
45 //-----------------------------------------------------------------
46 // Implementation
47 //-----------------------------------------------------------------
48 
49 PXDBackgroundModule::PXDBackgroundModule() :
50  Module(), m_outputDirectoryName(""),
51  m_doseReportingLevel(c_reportNTuple),
52  m_nfluxReportingLevel(c_reportNTuple),
53  m_occupancyReportingLevel(c_reportNTuple),
54  m_componentName(""), m_componentTime(0), m_integrationTime(20),
55  m_nielNeutrons(new TNiel(c_niel_neutronFile)),
56  m_nielProtons(new TNiel(c_niel_protonFile)),
57  m_nielPions(new TNiel(c_niel_pionFile)),
58  m_nielElectrons(new TNiel(c_niel_electronFile))
59 {
60  //Set module properties
61  setDescription("PXD background module");
62  setPropertyFlags(c_ParallelProcessingCertified); // specify this flag if you need parallel processing
63  // FIXME: This information can in principle be extracted from bg files, though not trivially.
64  addParam("componentName", m_componentName, "Background component name to process", m_componentName);
65  addParam("componentTime", m_componentTime, "Background component time", m_componentTime);
66  addParam("integrationTime", m_integrationTime, "PXD integration time", m_integrationTime);
67  addParam("doseReportingLevel", m_doseReportingLevel, "0 - no data, 1 - summary only, 2 - summary + ntuple", m_doseReportingLevel);
68  addParam("nfluxReportingLevel", m_nfluxReportingLevel, "0 - no data, 1 - summary only, 2 - summary + ntuple",
70  addParam("occupancyReportingLevel", m_occupancyReportingLevel, "0 - no data, 1 - summary only, 2 - summary + ntuple",
72  addParam("outputDirectory", m_outputDirectoryName, "Name of output directory", m_outputDirectoryName);
73 }
74 
75 const ROOT::Math::XYZVector& PXDBackgroundModule::pointToGlobal(VxdID sensorID, const ROOT::Math::XYZVector& local)
76 {
77  static ROOT::Math::XYZVector result(0, 0, 0);
78 
79  const PXD::SensorInfo& info = getInfo(sensorID);
80  result = info.pointToGlobal(local);
81  return result;
82 }
83 
84 const ROOT::Math::XYZVector& PXDBackgroundModule::vectorToGlobal(VxdID sensorID, const ROOT::Math::XYZVector& local)
85 {
86  static ROOT::Math::XYZVector result(0, 0, 0);
87 
88  const PXD::SensorInfo& info = getInfo(sensorID);
89  result = info.vectorToGlobal(local);
90  return result;
91 }
92 
94 {
95 }
96 
98 {
99  //Register collections
107 
108  RelationArray relDigitsMCParticles(storeDigits, storeMCParticles);
109  RelationArray relDigitsTrueHits(storeDigits, storeTrueHits);
110  RelationArray relMCParticlesTrueHits(storeMCParticles, storeTrueHits);
111  RelationArray relTrueHitsSimHits(storeTrueHits, storeSimHits);
112 
113  // Add two new StoreArrays
115  storeEnergyDeposits.registerInDataStore();
117  storeNeutronFluxes.registerInDataStore();
119  storeOccupancyEvents.registerInDataStore();
120 
121  //Store names to speed up creation later
122  m_storeFileMetaDataName = storeFileMetaData.getName();
123  m_storeBgMetaDataName = storeBgMetaData.getName();
124  m_storeMCParticlesName = storeMCParticles.getName();
125  m_storeSimHitsName = storeSimHits.getName();
126  m_storeTrueHitsName = storeTrueHits.getName();
127  m_storeDigitsName = storeDigits.getName();
128  m_relDigitsMCParticlesName = relDigitsMCParticles.getName();
129  m_relDigitsTrueHitsName = relDigitsTrueHits.getName();
130  m_relParticlesTrueHitsName = relMCParticlesTrueHits.getName();
131  m_relTrueHitsSimHitsName = relTrueHitsSimHits.getName();
132  m_storeEnergyDepositsName = storeEnergyDeposits.getName();
133  m_storeNeutronFluxesName = storeNeutronFluxes.getName();
134 
137 }
138 
140 {
141 }
142 
144 {
145  //Register collections
148  const StoreArray<MCParticle> storeMCParticles(m_storeMCParticlesName);
149  const StoreArray<PXDSimHit> storeSimHits(m_storeSimHitsName);
150  const StoreArray<PXDTrueHit> storeTrueHits(m_storeTrueHitsName);
151  const StoreArray<PXDDigit> storeDigits(m_storeDigitsName);
152  const StoreArray<PXDCluster> storeClsuters(m_storeClustersName);
153 
154  // Add two new StoreArrays
158 
159  // Relations
160  RelationArray relDigitsMCParticles(storeDigits, storeMCParticles, m_relDigitsMCParticlesName);
161  RelationArray relDigitsTrueHits(storeDigits, storeTrueHits, m_relDigitsTrueHitsName);
162  RelationArray relTrueHitsSimHits(storeTrueHits, storeSimHits, m_relTrueHitsSimHitsName);
163  RelationArray relTrueHitsMCParticles(storeMCParticles, storeTrueHits, m_relParticlesTrueHitsName);
164 
165  // unsigned long numberOfEvents = storeFileMetaData->getNEvents();
166  double currentComponentTime = storeBgMetaData->getRealTime();
167  if (currentComponentTime != m_componentTime)
168  B2FATAL("Mismatch in component times:\n"
169  << "Steering file: " << m_componentTime << "\n"
170  << "Background file: " << currentComponentTime);
171 
172  VxdID currentSensorID(0);
173  double currentSensorThickness(0);
174  double currentSensorArea(0);
175 
176  // Exposition and dose
178  B2DEBUG(100, "Expo and dose");
179  currentSensorID.setID(0);
180  double currentSensorMass(0);
181  for (const PXDSimHit& hit : storeSimHits) {
182  // Update if we have a new sensor
183  VxdID sensorID = hit.getSensorID();
184  if (sensorID != currentSensorID) {
185  currentSensorID = sensorID;
186  currentSensorThickness = getSensorThickness(currentSensorID);
187  currentSensorMass = getSensorMass(currentSensorID);
188  currentSensorArea = getSensorArea(currentSensorID);
189  }
190  double hitEnergy = hit.getElectrons() * Const::ehEnergy;
191  // Dose in Gy/smy, normalize by sensor mass
192  m_sensorData[currentSensorID].m_dose +=
193  (hitEnergy / Unit::J) / (currentSensorMass / 1000) * (c_smy / currentComponentTime);
194  // Exposition in GeV/cm2/s
195  m_sensorData[currentSensorID].m_expo += hitEnergy / currentSensorArea / (currentComponentTime / Unit::s);
197  const ROOT::Math::XYZVector localPos = hit.getPosIn();
198  const ROOT::Math::XYZVector globalPos = pointToGlobal(currentSensorID, localPos);
199  float globalPosXYZ[3];
200  globalPos.GetCoordinates(globalPosXYZ);
201  storeEnergyDeposits.appendNew(
202  sensorID.getLayerNumber(), sensorID.getLadderNumber(), sensorID.getSensorNumber(),
203  hit.getPDGcode(), hit.getGlobalTime(),
204  localPos.X(), localPos.Y(), globalPosXYZ, hitEnergy,
205  (hitEnergy / Unit::J) / (currentSensorMass / 1000) / (currentComponentTime / Unit::s),
206  (hitEnergy / Unit::J) / currentSensorArea / (currentComponentTime / Unit::s)
207  );
208  }
209  }
210  }
211 
212  // Neutron flux
214  B2DEBUG(100, "Neutron flux");
215  currentSensorID.setID(0);
216  for (const PXDTrueHit& hit : storeTrueHits) {
217  VxdID sensorID = hit.getSensorID();
218  // Update if we are on a new sensor
219  if (sensorID != currentSensorID) {
220  currentSensorID = sensorID;
221  currentSensorThickness = getSensorThickness(currentSensorID);
222  currentSensorArea = getSensorArea(currentSensorID);
223  }
224  // J(TrueHit) = abs(step)/thickness * correctionFactor;
225  ROOT::Math::XYZVector entryPos(hit.getEntryU(), hit.getEntryV(), hit.getEntryW());
226  ROOT::Math::XYZVector exitPos(hit.getExitU(), hit.getExitV(), hit.getExitW());
227  double stepLength = (exitPos - entryPos).R();
228  // Identify what particle we've got. We need type and kinetic energy.
229  // TODO: TrueHit must carry pdg or SimHit must carry energy.
230  // NOTE: MCParticles may get remapped, then SimHits still carry correct pdg.
231  const PXDSimHit* simhit = hit.getRelatedTo<PXDSimHit>();
232  if (!simhit) { //either something is very wrong, or we just don't have the relation. Try to find an appropriate SimHit manually.
233  double minDistance = 1.0e10;
234  for (const PXDSimHit& related : storeSimHits) {
235  double distance = (entryPos - related.getPosIn()).R();
236  if (distance < minDistance) {
237  minDistance = distance;
238  simhit = &related;
239  }
240  }
241  }
242  if (!simhit) {
243  B2WARNING("No related PXDSimHit found");
244  continue; //skip this true hit if the simhit is still null after setting it manually
245  }
246  // FIXME: Is there a difference between positrons and electrons wrt. NIEL?
247  // We fill neutronFluxBars with summary NIEL deposit for all kinds of particles by layer and component.
248  // Fluency plots are by component and are deposition histograms for a particular type of particle and compoonent.
249  // Special treatment of corrupt p's in TrueHits:
250  ROOT::Math::XYZVector hitMomentum(hit.getMomentum());
251  hitMomentum.SetX(std::isfinite(hitMomentum.X()) ? hitMomentum.X() : 0.0);
252  hitMomentum.SetY(std::isfinite(hitMomentum.Y()) ? hitMomentum.Y() : 0.0);
253  hitMomentum.SetZ(std::isfinite(hitMomentum.Z()) ? hitMomentum.Z() : 0.0);
254  int pdg = abs(simhit->getPDGcode());
255  double kineticEnergy(0.0);
256  double nielWeight(0.0);
257  if (pdg == Const::neutron.getPDGCode()) {
258  double m0 = Const::neutronMass;
259  kineticEnergy = sqrt(hitMomentum.Mag2() + m0 * m0) - m0;
260  nielWeight = m_nielNeutrons->getNielFactor(kineticEnergy / Unit::MeV);
261  }
262  if (pdg == Const::proton.getPDGCode()) {
263  double m0 = Const::protonMass;
264  kineticEnergy = sqrt(hitMomentum.Mag2() + m0 * m0) - m0;
265  nielWeight = m_nielProtons->getNielFactor(kineticEnergy / Unit::MeV);
266  }
267  if (pdg == Const::pi0.getPDGCode() || pdg == Const::pion.getPDGCode()) {
268  double m0 = Const::pi0Mass;
269  kineticEnergy = sqrt(hitMomentum.Mag2() + m0 * m0) - m0;
270  nielWeight = m_nielPions->getNielFactor(kineticEnergy / Unit::MeV);
271  }
272  if (pdg == Const::electron.getPDGCode()) {
273  double m0 = Const::electronMass;
274  kineticEnergy = sqrt(hitMomentum.Mag2() + m0 * m0) - m0;
275  nielWeight = m_nielElectrons->getNielFactor(kineticEnergy / Unit::MeV);
276  }
277  if (pdg == Const::photon.getPDGCode()) {
278  double m0 = 0.0;
279  kineticEnergy = sqrt(hitMomentum.Mag2() + m0 * m0) - m0;
280  }
281 
282  // Only set weight for supported particles
283  nielWeight = std::isfinite(nielWeight) ? nielWeight : 0.0;
284  m_sensorData[currentSensorID].m_neutronFlux += nielWeight * stepLength / currentSensorThickness / currentSensorArea /
285  currentComponentTime * c_smy;
286 
287  // Store data in a PXDNeutronFluxEvent object
289  ROOT::Math::XYZVector localPos(hit.getU(), hit.getV(), hit.getW());
290  const ROOT::Math::XYZVector globalPos = pointToGlobal(currentSensorID, localPos);
291  float globalPosXYZ[3];
292  globalPos.GetCoordinates(globalPosXYZ);
293  ROOT::Math::XYZVector localMom = hit.getMomentum();
294  const ROOT::Math::XYZVector globalMom = vectorToGlobal(currentSensorID, localMom);
295  float globalMomXYZ[3];
296  globalMom.GetCoordinates(globalMomXYZ);
297  storeNeutronFluxes.appendNew(
298  sensorID.getLayerNumber(), sensorID.getLadderNumber(), sensorID.getSensorNumber(),
299  simhit->getPDGcode(), simhit->getGlobalTime(),
300  hit.getU(), hit.getV(), globalPosXYZ, globalMomXYZ, kineticEnergy,
301  stepLength, nielWeight,
302  stepLength / currentSensorThickness / currentSensorArea / (currentComponentTime / Unit::s),
303  nielWeight * stepLength / currentSensorThickness / currentSensorArea / (currentComponentTime / Unit::s)
304  );
305  }
306  }
307  }
308 
309  // Occupancy
311  B2DEBUG(100, "Fired pixels");
312  currentSensorID.setID(0);
313  double currentSensorCut = 0;
314  // Store fired pixels: count number of digits over threshold
315  std::map<VxdID, std::vector<float> > firedPixels;
316  for (const PXDDigit& storeDigit : storeDigits) {
317  // Filter out digits with signals below zero-suppression threshold
318  // ARE THRE SUCH DIGITS?
319  VxdID sensorID = storeDigit.getSensorID();
320  if (sensorID != currentSensorID) {
321  currentSensorID = sensorID;
322  auto info = getInfo(sensorID);
323  currentSensorCut = info.getChargeThreshold();
324  }
325  B2DEBUG(30, "Digit charge: " << storeDigit.getCharge() << " threshold: " << currentSensorCut);
326  if (storeDigit.getCharge() < currentSensorCut) continue;
327  B2DEBUG(30, "Passed.");
328  firedPixels[sensorID].push_back(storeDigit.getCharge());
329  }
330  // Process the map
331  for (auto idAndSet : firedPixels) {
332  VxdID sensorID = idAndSet.first;
333  double sensorArea = getSensorArea(sensorID);
334  int nFired = idAndSet.second.size();
335  double fired = nFired / (currentComponentTime / Unit::s) / sensorArea;
336  m_sensorData[sensorID].m_fired += fired;
337  }
338 
339  B2DEBUG(100, "Occupancy");
340  currentSensorID.setID(0);
341  int nPixels = 0;
342  for (auto cluster : storeClsuters) {
343  VxdID sensorID = cluster.getSensorID();
344  if (currentSensorID != sensorID) {
345  currentSensorID = sensorID;
346  auto info = getInfo(sensorID);
347  nPixels = info.getUCells() * info.getVCells();
348  }
349 
350  double w_acceptance = m_integrationTime / currentComponentTime;
351  double occupancy = 1.0 / nPixels * cluster.getSize();
352  m_sensorData[sensorID].m_occupancy += w_acceptance * occupancy;
353 
355  storeOccupancyEvents.appendNew(
356  sensorID.getLayerNumber(), sensorID.getLadderNumber(),
357  sensorID.getSensorNumber(),
358  cluster.getU(), cluster.getV(), cluster.getSize(),
359  cluster.getCharge(), occupancy
360  );
361  }
362  }
363  }
364 }
365 
367 {
368 }
369 
370 
372 {
373  // Write out m_data
374  ofstream outfile;
375  string outfileName(m_outputDirectoryName + m_componentName + "_summary.txt");
376  outfile.open(outfileName.c_str(), ios::out | ios::trunc);
377  outfile << "component_name\t"
378  << "component_time\t"
379  << "layer\t"
380  << "ladder\t"
381  << "sensor\t"
382  << "dose\t"
383  << "expo\t"
384  << "neutronFlux\t"
385  << "fired\t"
386  << "occupancy"
387  << endl;
388  double componentTime = m_componentTime / Unit::us;
389  for (auto vxdSensor : m_sensorData) {
390  outfile << m_componentName.c_str() << "\t"
391  << componentTime << "\t"
392  << vxdSensor.first.getLayerNumber() << "\t"
393  << vxdSensor.first.getLadderNumber() << "\t"
394  << vxdSensor.first.getSensorNumber() << "\t"
395  << vxdSensor.second.m_dose << "\t"
396  << vxdSensor.second.m_expo << "\t"
397  << vxdSensor.second.m_neutronFlux << "\t"
398  << vxdSensor.second.m_fired << "\t"
399  << vxdSensor.second.m_occupancy
400  << endl;
401  }
402  outfile << endl;
403 }
double R
typedef autogenerated by FFTW
static const ParticleType neutron
neutron particle
Definition: Const.h:666
static const ParticleType pi0
neutral pion particle
Definition: Const.h:665
static const ChargedStable pion
charged pion particle
Definition: Const.h:652
static const double electronMass
electron mass
Definition: Const.h:676
static const double neutronMass
neutron mass
Definition: Const.h:683
static const ChargedStable proton
proton particle
Definition: Const.h:654
static const double ehEnergy
Energy needed to create an electron-hole pair in Si at std.
Definition: Const.h:688
static const double protonMass
proton mass
Definition: Const.h:680
static const ParticleType photon
photon particle
Definition: Const.h:664
static const double pi0Mass
neutral pion mass
Definition: Const.h:682
static const ChargedStable electron
electron particle
Definition: Const.h:650
@ c_Persistent
Object is available during entire execution time.
Definition: DataStore.h:60
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
The PXD digit class.
Definition: PXDDigit.h:27
Class PXDSimHit - Geant4 simulated hit for the PXD.
Definition: PXDSimHit.h:24
Class PXDTrueHit - Records of tracks that either enter or leave the sensitive volume.
Definition: PXDTrueHit.h:31
static const unsigned short c_reportNTuple
Summary and NTuple.
std::string m_storeFileMetaDataName
Name of the persistent FileMetaData object.
unsigned short m_nfluxReportingLevel
0 - no data, 1 - summary only, 2 - ntuple
const ROOT::Math::XYZVector & vectorToGlobal(VxdID sensorID, const ROOT::Math::XYZVector &local)
Convert local vector coordinates to global.
const ROOT::Math::XYZVector & pointToGlobal(VxdID sensorID, const ROOT::Math::XYZVector &local)
Convert local sensor coordinates to global.
std::string m_storeEnergyDepositsName
PXDEnergyDepositEvents StoreArray name.
const double c_smy
Seconds in snowmass year.
unsigned short m_doseReportingLevel
0 - no data, 1 - summary only, 2 - ntuple
std::string m_storeOccupancyEventsName
PXDOccupancyEvents StoreArray name.
std::map< VxdID, SensorData > m_sensorData
Struct to hold sensor-wise background data.
virtual void initialize() override
Initialize module.
std::string m_relTrueHitsSimHitsName
PXDTrueHitsToPXDSimHits RelationArray name.
double m_integrationTime
Integration time of PXD.
std::string m_relDigitsMCParticlesName
StoreArray name of PXDDigits to MCParticles relation.
virtual void event() override
Event processing.
double getSensorMass(VxdID sensorID) const
Return mass of the sensor with the given sensor ID.
static const unsigned short c_reportNone
No reporting.
virtual void endRun() override
End-of-run tasks.
std::string m_storeNeutronFluxesName
PXDNeutronFluxEvents StoreArray name.
std::string m_storeTrueHitsName
PXDTrueHits StoreArray name.
virtual void terminate() override
Final summary and cleanup.
std::unique_ptr< TNiel > m_nielNeutrons
Pointer to Niel table for neutrons.
std::string m_storeMCParticlesName
MCParticles StoreArray name.
std::unique_ptr< TNiel > m_nielProtons
Pointer to Niel table for protons.
double getSensorThickness(VxdID sensorID) const
Return thickness of the sensor with the given sensor ID.
const PXD::SensorInfo & getInfo(VxdID sensorID) const
This is a shortcut to getting PXD::SensorInfo from the GeoCache.
std::unique_ptr< TNiel > m_nielPions
Pointer to Niel table for pions.
virtual void beginRun() override
Start-of-run initializations.
std::string m_storeBgMetaDataName
Name of the persistent BackgroundMetaDta object.
double getSensorArea(VxdID sensorID) const
Return area of the sensor with the given sensor ID.
std::string m_outputDirectoryName
Path to directory where output data will be stored.
std::string m_storeDigitsName
PXDDigits StoreArray name.
std::string m_storeClustersName
PXDClusters StoreArray name.
std::unique_ptr< TNiel > m_nielElectrons
Pointer to Niel table for electrons.
std::string m_relParticlesTrueHitsName
MCParticlesToPXDTrueHits RelationArray name.
std::string m_componentName
Name of the current bg component.
double m_componentTime
Time of current component.
unsigned short m_occupancyReportingLevel
0 - no data, 1 - summary only, 2 - ntuple
std::string m_storeSimHitsName
PXDSimHits StoreArray name.
std::string m_relDigitsTrueHitsName
StoreArray name of PXDDigits to PXDTrueHits relation.
virtual ~PXDBackgroundModule()
Destructor.
Specific implementation of SensorInfo for PXD Sensors which provides additional pixel specific inform...
Definition: SensorInfo.h:23
Low-level class to create/modify relations between StoreArrays.
Definition: RelationArray.h:62
const std::string & getName() const
Return name under which the object is saved in the DataStore.
bool registerInDataStore(DataStore::EStoreFlags storeFlags=DataStore::c_WriteOut)
Register the object/array in the DataStore.
T * appendNew()
Construct a new T object at the end of the array.
Definition: StoreArray.h:246
Type-safe access to single objects in the data store.
Definition: StoreObjPtr.h:96
static const double us
[microsecond]
Definition: Unit.h:97
static const double J
[joule]
Definition: Unit.h:116
static const double MeV
[megaelectronvolt]
Definition: Unit.h:114
static const double s
[second]
Definition: Unit.h:95
float getGlobalTime() const override
Return the time of the electron deposition.
Definition: VXDSimHit.h:78
int getPDGcode() const
Return the PDG code of the particle causing the electron deposition.
Definition: VXDSimHit.h:68
Class to uniquely identify a any structure of the PXD and SVD.
Definition: VxdID.h:33
baseType getSensorNumber() const
Get the sensor id.
Definition: VxdID.h:100
void setID(baseType id)
Set the unique id.
Definition: VxdID.h:105
baseType getLadderNumber() const
Get the ladder id.
Definition: VxdID.h:98
baseType getLayerNumber() const
Get the layer id.
Definition: VxdID.h:96
TNiel - the class providing values for NIEL factors.
Definition: niel_fun.h:17
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
double sqrt(double a)
sqrt for double
Definition: beamHelpers.h:28
Namespace to encapsulate code needed for simulation and reconstrucion of the PXD.
Abstract base class for different kinds of events.