Belle II Software  release-06-02-00
VXDSimpleClusterizerModule.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 <tracking/modules/VXDTFHelperTools/VXDSimpleClusterizerModule.h>
10 #include <vxd/geometry/SensorInfoBase.h>
11 #include <vxd/geometry/GeoCache.h>
12 
13 #include <framework/datastore/StoreObjPtr.h>
14 #include <framework/dataobjects/EventMetaData.h>
15 #include <framework/logging/Logger.h>
16 
17 //C++ std lib
18 #include <vector>
19 using std::vector;
20 
21 #include <string>
22 using std::string;
23 
24 #include <cmath>
25 using std::sin;
26 using std::cos;
27 using std::sqrt;
28 
29 //root stuff
30 #include <TRandom.h>
31 
32 using namespace Belle2;
33 
34 REG_MODULE(VXDSimpleClusterizer)
35 
37 {
38  InitializeVariables();
39 
40 
41  setDescription("The VXDSimpleClusterizerModule generates PXD/SVD Clusters using TrueHits. Energy-deposit threshold and gaussian smearing can be chosen, non-primary-particles can be filtered as well. Its purpose is fast clusterizing for tracking test procedures, using standardized PXD/SVD-Cluster");
42  setPropertyFlags(c_ParallelProcessingCertified);
43 
44  addParam("energyThresholdU", m_energyThresholdU,
45  "particles with energy deposit in U lower than this will not create a cluster in SVD (GeV)", double(17.4E-6));
46  addParam("energyThresholdV", m_energyThresholdV,
47  "particles with energy deposit in V lower than this will not create a cluster in SVD (GeV)", double(28.6E-6));
48  addParam("energyThreshold", m_energyThreshold,
49  "particles with energy deposit lower than this will not create a cluster in PXD (GeV)", double(7E-6));
50  addParam("onlyPrimaries", m_onlyPrimaries, "if true use only primary particles from the generator no particles created by Geant4",
51  false);
52  addParam("uniSigma", m_uniSigma,
53  "you can define the sigma of the smearing. Standard value is the sigma of the unifom distribution for 0-1: 1/sqrt(12)",
54  double(1. / sqrt(12.)));
55  addParam("setMeasSigma", m_setMeasSigma,
56  "if positive value (in cm) is given it will be used as the sigma to smear the Clusters otherwise pitch/uniSigma will be used",
57  -1.0);
58  addParam("PXDTrueHits", m_pxdTrueHitsName,
59  "PXDTrueHit collection name", string(""));
60  addParam("SVDTrueHits", m_svdTrueHitsName,
61  "SVDTrueHit collection name", string(""));
62  addParam("MCParticles", m_mcParticlesName,
63  "MCParticle collection name", string(""));
64  addParam("PXDClusters", m_pxdClustersName,
65  "PXDCluster collection name", string(""));
66  addParam("SVDClusters", m_svdClustersName,
67  "SVDCluster collection name", string(""));
68 }
69 
70 
72 {
73  //input containers:
75  m_pxdTrueHits.isOptional(m_pxdTrueHitsName);
76  m_svdTrueHits.isOptional(m_svdTrueHitsName);
77 
78  // initializing StoreArrays for clusters. needed to give them the names set by parameters
81 
82  if (m_pxdTrueHits.isOptional() == true) {
83 
84  //Relations to cluster objects only if the ancestor relations exist:
87  m_pxdTrueHitsName = m_pxdTrueHits.getName();
88 
89  if (m_mcParticles.isOptional() == true) {
92  }
93  }
94 
95  if (m_svdTrueHits.isOptional() == true) {
96 
97  //Relations to cluster objects only if the ancestor relations exist:
100  m_svdTrueHitsName = m_svdTrueHits.getName();
101 
102  if (m_mcParticles.isOptional() == true) {
105  }
106  }
107 }
108 
109 
110 
112 {
113  string paramValue;
114  if (m_onlyPrimaries == true) {
115  paramValue = "true, means that there are no secondary hits (for 1-track events this means no ghost hits guaranteed)";
116  } else {
117  paramValue = "false, means that secondary hits can occur and increase the rate of ghost hits";
118  }
119  B2INFO("VXDSimpleClusterizer: parameter onlyPrimaries is set to " << paramValue);
120 
122 }
123 
124 
125 
127 {
128  // counter for cases when a trueHit god discarded:
129  int discardedPXDEdeposit = 0, discardedSVDEdeposit = 0, discardedPXDFake = 0, discardedSVDFake = 0;
130 
131  const StoreObjPtr<EventMetaData> eventMetaDataPtr("EventMetaData", DataStore::c_Event);
132 
133  B2DEBUG(5, "******* VXDSimpleClusterizerModule processing event number: " << eventMetaDataPtr->getEvent() << " *******");
134 
135 
136  //check all the input containers. First: MCParticles
137  int nMcParticles = m_mcParticles.getEntries();
138  if (nMcParticles == 0) {B2DEBUG(100, "MCTrackFinder: MCParticlesCollection is empty!");}
139  //PXD
140  int nPxdTrueHits = m_pxdTrueHits.getEntries();
141  if (nPxdTrueHits == 0) {B2DEBUG(100, "MCTrackFinder: PXDHitsCollection is empty!");}
142  //SVD
143  int nSvdTrueHits = m_svdTrueHits.getEntries();
144  if (nSvdTrueHits == 0) {B2DEBUG(100, "MCTrackFinder: SVDHitsCollection is empty!");}
145  B2DEBUG(175, "found " << nMcParticles << "/" << nPxdTrueHits << "/" << nSvdTrueHits << " mcParticles, pxdTrueHits, svdTrueHits");
146 
147 
148  double sigmaU = m_setMeasSigma;
149  double sigmaV = m_setMeasSigma;
150 
151 
153  for (unsigned int currentTrueHit = 0; int (currentTrueHit) not_eq nPxdTrueHits; ++currentTrueHit) {
154  B2DEBUG(175, "begin PXD current TrueHit: " << currentTrueHit << " of nPxdTrueHits total: " << nPxdTrueHits);
155 
156  const PXDTrueHit* aPxdTrueHit = m_pxdTrueHits[currentTrueHit];
157  const MCParticle* aMcParticle = aPxdTrueHit->getRelatedFrom<MCParticle>();
158  unsigned int particleID = std::numeric_limits<unsigned int>::max();
159 
160  if (aMcParticle != nullptr) { particleID = aMcParticle->getArrayIndex(); }
161 
162  double energy = aPxdTrueHit->getEnergyDep();
163 
164 
165  if (m_onlyPrimaries == true) { // ingore hits not comming from primary particles (e.g material effects particles)
166  if (aMcParticle == nullptr or aMcParticle->hasStatus(MCParticle::c_PrimaryParticle) == false) {
167  m_fakePXDHitCtr++;
168  discardedPXDFake++;
169  continue; // jump to next pxdTrueHit
170  }
171  }
172 
173  B2DEBUG(100, " PXD, current TrueHit " << currentTrueHit << " connected to " << particleID << " has an energy deposit of " <<
174  energy * 1000.0 << "MeV ");
175  if (energy < m_energyThreshold) { //ignore hit if energy deposit is too small
176  B2DEBUG(100, " PXD, TrueHit discarded because of energy deposit too small");
177  m_weakPXDHitCtr++;
178  discardedPXDEdeposit++;
179  continue;
180  }
181 
182  //smear the pxdTrueHit and get needed variables for storing
183  VxdID aVXDId = aPxdTrueHit->getSensorID();
184  double uTrue = aPxdTrueHit->getU();
185  double vTrue = aPxdTrueHit->getV();
186  double u = -20;
187  double v = -20;
188  if (m_setMeasSigma < 0.0) {
189  const VXD::SensorInfoBase* sensorInfo = &VXD::GeoCache::getInstance().getSensorInfo(aVXDId);
190  sigmaU = sensorInfo->getUPitch(uTrue) * m_uniSigma;
191  sigmaV = sensorInfo->getVPitch(vTrue) * m_uniSigma;
192  }
193  B2DEBUG(175, "sigU sigV: " << sigmaU << " " << sigmaV);
194 
195  if (m_setMeasSigma != 0) {
196  u = gRandom->Gaus(uTrue, sigmaU);
197  v = gRandom->Gaus(vTrue, sigmaV);
198  } else {
199  u = uTrue;
200  v = vTrue;
201  }
202 
203  if (m_setMeasSigma == 0 and m_uniSigma == 0) {
204  // in this case, the hits will not be smeared, but still we need some measurement error-values to be able to do some fitting... WARNING currently arbritary values here, better solution recommended!
205  sigmaU = 0.000001;
206  sigmaV = 0.000001;
207  }
208 
224  // Save as new 2D-PXD-cluster
225  PXDCluster* newCluster = m_pxdClusters.appendNew(aVXDId, u, v, sigmaU, sigmaV, 0, 1, 1, 1, 1, 1, 1, 1);
226  // add relations
227  newCluster->addRelationTo(m_pxdTrueHits[currentTrueHit]);
228 
229  if (particleID != std::numeric_limits<unsigned int>::max()) {
230  newCluster->addRelationTo(m_mcParticles[particleID]);
231  B2DEBUG(20, "mcParticle " << particleID << " has " << aMcParticle->getRelationsTo<PXDCluster>().size() <<
232  " relations to PXD clusters");
233  }
234  }
235 
236 
237 
239  for (unsigned int currentTrueHit = 0; int (currentTrueHit) not_eq nSvdTrueHits; ++currentTrueHit) {
240  B2DEBUG(175, "begin SVD current TrueHit: " << currentTrueHit << " of nSvdTrueHits total: " << nSvdTrueHits);
241 
242  const SVDTrueHit* aSvdTrueHit = m_svdTrueHits[currentTrueHit];
243  const MCParticle* aMcParticle = aSvdTrueHit->getRelatedFrom<MCParticle>();
244  unsigned int particleID = std::numeric_limits<unsigned int>::max();
245 
246  if (m_onlyPrimaries == true) { // ingore hits not comming from primary particles (e.g material effects particles)
247  if (aMcParticle == nullptr or aMcParticle->hasStatus(MCParticle::c_PrimaryParticle) == false) {
248  m_fakeSVDHitCtr++;
249  discardedSVDFake++;
250  continue; // jump to next svdTrueHit
251  }
252  }
253 
254  if (aMcParticle != nullptr) { particleID = aMcParticle->getArrayIndex(); }
255  double energy = aSvdTrueHit->getEnergyDep();
256 
257  B2DEBUG(100, " SVD, current TrueHit " << currentTrueHit << " connected to " << particleID << " has an energy deposit of " <<
258  energy * 1000.0 << "MeV ");
259  if (energy < (m_energyThresholdU + m_energyThresholdV)) { //ignore hit if energy deposity is too snall
260  m_weakSVDHitCtr++;
261  discardedSVDEdeposit++;
262  B2DEBUG(100, " SVD, TrueHit discarded because of energy deposit too small");
263  continue;
264  }
265 
266 
267  // smear the SvdTrueHit and get needed variables for storing
268  VxdID aVXDId = aSvdTrueHit->getSensorID();
269  double uTrue = aSvdTrueHit->getU();
270  double vTrue = aSvdTrueHit->getV();
271  double u = -20;
272  double v = -20;
273  if (m_setMeasSigma < 0.0) {
274  const VXD::SensorInfoBase* sensorInfo = &VXD::GeoCache::getInstance().getSensorInfo(aVXDId);
275  sigmaU = sensorInfo->getUPitch(uTrue) * m_uniSigma;
276  sigmaV = sensorInfo->getVPitch(vTrue) * m_uniSigma;
277  }
278  B2DEBUG(150, "sigU sigV: " << sigmaU << " " << sigmaV);
279 
280  if (m_setMeasSigma != 0) {
281  u = gRandom->Gaus(uTrue, sigmaU);
282  v = gRandom->Gaus(vTrue, sigmaV);
283  } else {
284  u = uTrue;
285  v = vTrue;
286  }
287 
288  if (m_setMeasSigma == 0) {
289  // in this case, the hits will not be smeared, but still we need some measurement error-values to be able to do some fitting... WARNING currently arbritary values here, better solution recommended!
290  sigmaU = 0.000001;
291  sigmaV = 0.000001;
292  }
293 
294  // Save as two new 1D-SVD-clusters
295  double timeStamp = m_svdTrueHits[currentTrueHit]->getGlobalTime();
296 
310  SVDCluster* newClusterU = m_svdClusters.appendNew(aVXDId, true, u, sigmaU, timeStamp, 0, 1, 1,
311  3, 1); // in a typical situation 3-5 Strips are excited per Hit -> set to 3
312  // add relations to u-cluster
313  newClusterU->addRelationTo(m_svdTrueHits[currentTrueHit]);
314 
315  SVDCluster* newClusterV = m_svdClusters.appendNew(aVXDId, false, v, sigmaV, timeStamp, 0, 1, 1, 3, 1);
316  // add relations to v-cluster
317  newClusterV->addRelationTo(m_svdTrueHits[currentTrueHit]);
318 
319  if (particleID != std::numeric_limits<unsigned int>::max()) {
320  newClusterU->addRelationTo(m_mcParticles[particleID]);
321  newClusterV->addRelationTo(m_mcParticles[particleID]);
322  B2DEBUG(20, "mcParticle " << particleID << " has " << aMcParticle->getRelationsTo<SVDCluster>().size() <<
323  " relations to SVD clusters");
324  }
325 
326  }
327 
328  B2DEBUG(10, "------------------------------------------------------");
329 
330  B2DEBUG(10, "VXDSimpleClusterizerModule: Number of PXDHits: " << nPxdTrueHits);
331  B2DEBUG(10, "VXDSimpleClusterizerModule: Number of SVDDHits: " << nSvdTrueHits);
332  B2DEBUG(10, "VXDSimpleClusterizerModule: total Number of MCParticles: " << nMcParticles);
333  B2DEBUG(10, "pxdClusters.getEntries()" << m_pxdClusters.getEntries());
334  B2DEBUG(10, "svdClusters.getEntries()" << m_svdClusters.getEntries());
335  B2DEBUG(10, "------------------------------------------------------");
336 
337  B2DEBUG(1, "VXDSimpleClusterizer - event " << eventMetaDataPtr->getEvent() << ":\n" << "of " << nPxdTrueHits << "/" << nSvdTrueHits
338  << " PXD-/SVDTrueHits, " << discardedPXDEdeposit << "/" << discardedSVDEdeposit << " hits were discarded bec. of low E-deposit & "
339  << discardedPXDFake << "/" << discardedSVDFake << " hits were discarded bec. of being a fake. " << m_pxdClusters.getEntries() << "/"
340  << m_svdClusters.getEntries() << " Clusters were stored.\n");
341 }
342 
343 
344 
346 {
347  B2INFO("VXDSimpleClusterizerModule::EndRun:\nSimpleClusterizerModule discarded " << m_weakPXDHitCtr << " PXDTrueHits and " <<
348  m_weakSVDHitCtr << " SVDTrueHits because of low E-deposit-threshold and discarded " << m_fakePXDHitCtr << " PXDTrueHits and " <<
349  m_fakeSVDHitCtr << " SVDTrueHits because they were fake");
350 }
@ c_ErrorIfAlreadyRegistered
If the object/array was already registered, produce an error (aborting initialisation).
Definition: DataStore.h:72
@ c_Event
Different object in each event, all objects/arrays are invalidated after event() function has been ca...
Definition: DataStore.h:59
A Class to store the Monte Carlo particle information.
Definition: MCParticle.h:32
@ c_PrimaryParticle
bit 0: Particle is primary particle.
Definition: MCParticle.h:47
bool hasStatus(unsigned short int bitmask) const
Return if specific status bit is set.
Definition: MCParticle.h:129
int getArrayIndex() const
Get 0-based index of the particle in the corresponding MCParticle list.
Definition: MCParticle.h:244
Base class for Modules.
Definition: Module.h:72
The PXD Cluster class This class stores all information about reconstructed PXD clusters The position...
Definition: PXDCluster.h:30
Class PXDTrueHit - Records of tracks that either enter or leave the sensitive volume.
Definition: PXDTrueHit.h:31
void addRelationTo(const RelationsInterface< BASE > *object, float weight=1.0, const std::string &namedRelation="") const
Add a relation from this object to another object (with caching).
RelationVector< TO > getRelationsTo(const std::string &name="", const std::string &namedRelation="") const
Get the relations that point from this object to another store array.
FROM * getRelatedFrom(const std::string &name="", const std::string &namedRelation="") const
Get the object from which this object has a relation.
The SVD Cluster class This class stores all information about reconstructed SVD clusters.
Definition: SVDCluster.h:28
Class SVDTrueHit - Records of tracks that either enter or leave the sensitive volume.
Definition: SVDTrueHit.h:33
bool isOptional(const std::string &name="")
Tell the DataStore about an optional input.
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
int getEntries() const
Get the number of objects in the array.
Definition: StoreArray.h:216
bool registerRelationTo(const StoreArray< TO > &toArray, DataStore::EDurability durability=DataStore::c_Event, DataStore::EStoreFlags storeFlags=DataStore::c_WriteOut, const std::string &namedRelation="") const
Register a relation to the given StoreArray.
Definition: StoreArray.h:140
Type-safe access to single objects in the data store.
Definition: StoreObjPtr.h:95
Module to convert TrueHits into Clusters using a simplified process.
std::string m_svdTrueHitsName
SVDTrueHit collection name.
std::string m_svdClustersName
SVDCluster collection name.
int m_fakePXDHitCtr
counts PXDHits which were not caused by a primary partice
double m_energyThreshold
set energy threshold for PXDClusters in GeV (standard is 7E-6)
double m_energyThresholdV
set energy threshold for SVDClusters in v-direction in GeV (standard is 28.6E-6)
StoreArray< SVDTrueHit > m_svdTrueHits
the storeArray for svdTrueHits as member, is faster than recreating link for each event
StoreArray< PXDTrueHit > m_pxdTrueHits
the storeArray for pxdTrueHits as member, is faster than recreating link for each event
void initialize() override
Initialize the Module.
double m_uniSigma
you can define the sigma of the smearing.
std::string m_mcParticlesName
MCParticle collection name.
StoreArray< SVDCluster > m_svdClusters
the storeArray for svdClusters as member, is faster than recreating link for each event
void event() override
This method is the core of the module.
void endRun() override
This method is called if the current run ends.
int m_weakPXDHitCtr
counts PXDHits whose energy deposit is lower than energyThreshold
int m_weakSVDHitCtr
counts SVDHits whose energy deposit is lower than energyThreshold
std::string m_pxdClustersName
PXDCluster collection name.
double m_setMeasSigma
if positive value (in cm) is given it will be used as the sigma to smear the Clusters otherwise pitch...
void beginRun() override
Called when entering a new run.
void InitializeVariables()
initialize variables to avoid nondeterministic behavior
std::string m_pxdTrueHitsName
PXDTrueHit collection name.
StoreArray< PXDCluster > m_pxdClusters
the storeArray for pxdClusters as member, is faster than recreating link for each event
StoreArray< MCParticle > m_mcParticles
the storeArray for mcParticles as member, is faster than recreating link for each event
bool m_onlyPrimaries
set True if you do not want to have hits by secondary particles
int m_fakeSVDHitCtr
counts SVDHits which were not caused by a primary partice
double m_energyThresholdU
set energy threshold for SVDClusters in u-direction in GeV (standard is 17.4E-6)
float getV() const
Return local v coordinate of hit.
Definition: VXDTrueHit.h:77
float getEnergyDep() const
Return energy deposited during traversal of sensor.
Definition: VXDTrueHit.h:93
VxdID getSensorID() const
Return the Sensor ID.
Definition: VXDTrueHit.h:71
float getU() const
Return local u coordinate of hit.
Definition: VXDTrueHit.h:75
const SensorInfoBase & getSensorInfo(Belle2::VxdID id) const
Return a referecne to the SensorInfo of a given SensorID.
Definition: GeoCache.cc:66
static GeoCache & getInstance()
Return a reference to the singleton instance.
Definition: GeoCache.cc:213
Base class to provide Sensor Information for PXD and SVD.
double getUPitch(double v=0) const
Return the pitch of the sensor.
double getVPitch(double v=0) const
Return the pitch of the sensor.
Class to uniquely identify a any structure of the PXD and SVD.
Definition: VxdID.h:33
#define REG_MODULE(moduleName)
Register the given module (without 'Module' suffix) with the framework.
Definition: Module.h:650
Abstract base class for different kinds of events.