Belle II Software  release-05-02-19
ECLCRFinderModule.cc
1 /**************************************************************************
2  * BASF2 (Belle Analysis Framework 2) *
3  * Copyright(C) 2016 - Belle II Collaboration *
4  * *
5  * Belle II Connected Region Finder (CRF). Starting with 'seed' cells *
6  * above an energy energyCut0. Add neighbouring crystals above energyCut2.*
7  * If neighbouring crystal is above energyCut1, repeat this. Timing cuts *
8  * can be set for each digit type and the energy cuts can be made *
9  * background dependent using the event-by-event background measurements. *
10  * Digits with failed time fits automatically pass timing cuts by default.*
11  * The CRF must run once before the splitters and splitters must only use *
12  * digits contained in a CR. Digits from different CRs must not be mixed. *
13  * *
14  * Author: The Belle II Collaboration *
15  * Contributors: Torben Ferber (ferber@physics.ubc.ca) *
16  * *
17  * This software is provided "as is" without any warranty. *
18  **************************************************************************/
19 
20 // THIS MODULE
21 #include <ecl/modules/eclCRFinder/ECLCRFinderModule.h>
22 
23 // FRAMEWORK
24 #include <framework/gearbox/Unit.h>
25 #include <framework/logging/Logger.h>
26 
27 //ECL
28 #include <ecl/geometry/ECLNeighbours.h>
29 #include <ecl/dataobjects/ECLCalDigit.h>
30 #include <ecl/dataobjects/ECLConnectedRegion.h>
31 
32 // MDST
33 #include <mdst/dataobjects/EventLevelClusteringInfo.h>
34 
35 // NAMESPACE(S)
36 using namespace Belle2;
37 
38 //-----------------------------------------------------------------
39 // Register the Module
40 //-----------------------------------------------------------------
41 REG_MODULE(ECLCRFinder)
42 REG_MODULE(ECLCRFinderPureCsI)
43 
44 //-----------------------------------------------------------------
45 // Implementation
46 //-----------------------------------------------------------------
47 ECLCRFinderModule::ECLCRFinderModule() : Module(), m_eclCalDigits(eclCalDigitArrayName()),
48  m_eclConnectedRegions(eclConnectedRegionArrayName()), m_eventLevelClusteringInfo(eventLevelClusteringInfoName())
49 {
50  // Set description
51  setDescription("ECLCRFinderModule");
52 
53  // Parallel processing certification.
54  setPropertyFlags(c_ParallelProcessingCertified);
55 
56  // Add module parameters.
57  addParam("energyCut0", m_energyCut[0], "Seed energy cut.", 10.0 * Belle2::Unit::MeV);
58  addParam("energyCut1", m_energyCut[1], "Growth energy cut.", 1.5 * Belle2::Unit::MeV);
59  addParam("energyCut2", m_energyCut[2], "Digit energy cut.", 0.5 * Belle2::Unit::MeV);
60  addParam("energyCutBkgd0", m_energyCutBkgd[0], "Seed energy cut (for high background).", 10.0 * Belle2::Unit::MeV);
61  addParam("energyCutBkgd1", m_energyCutBkgd[1], "Growth energy cut (for high background).", 1.5 * Belle2::Unit::MeV);
62  addParam("energyCutBkgd2", m_energyCutBkgd[2], "Digit energy cut (for high background).", 0.5 * Belle2::Unit::MeV);
63  addParam("timeCut0", m_timeCut[0], "Seed time cut (negative values for residual cut).", 99999.);
64  addParam("timeCut1", m_timeCut[1], "Growth time cut (negative values for residual cut).", 99999.);
65  addParam("timeCut2", m_timeCut[2], "Digit time cut (negative values for residual cut).", 99999.);
66  addParam("mapType0", m_mapType[0], "Map type for seed crystals.", std::string("N"));
67  addParam("mapType1", m_mapType[1], "Map type for growth crystals.", std::string("N"));
68  addParam("mapPar0", m_mapPar[0],
69  "Map parameter for seed crystals (radius (type=R), integer (for type=N) or fraction (for type=MC)).", 1.0);
70  addParam("mapPar1", m_mapPar[1],
71  "Map parameter for growth crystals (radius (type=R), integer (for type=N) or fraction (for type=MC)).", 1.0);
72  addParam("useBackgroundLevel", m_useBackgroundLevel, "Use background dependent time and energy cuts.", 0);
73  addParam("skipFailedTimeFitDigits", m_skipFailedTimeFitDigits, "Digits with failed fits are skipped when checking timing cuts.", 0);
74  addParam("fullBkgdCount", m_fullBkgdCount, "Full background count (via eventLevelClusteringInfo).", 182);
75 
76 }
77 
79 {
80  ;
81 }
82 
84 {
85  B2DEBUG(200, "ECLCRFinderModule::initialize()");
86 
87  // Register dataobjects.
88  m_eclCalDigits.registerInDataStore(eclCalDigitArrayName());
91 
92  // Register relations.
93  m_eclConnectedRegions.registerRelationTo(m_eclCalDigits);
94 
95  // Check user inputs.
96  if (m_energyCut[0] < m_energyCut[1]) B2FATAL("ECLCRFinderModule::initialize(): m_energyCut[0] must be larger than m_energyCut[1].");
97  if (m_energyCut[1] < m_energyCut[2]) B2FATAL("ECLCRFinderModule::initialize(): m_energyCut[1] must be larger than m_energyCut[2].");
98  if (m_energyCut[0] < m_energyCut[2]) B2FATAL("ECLCRFinderModule::initialize(): m_energyCut[0] must be larger than m_energyCut[2].");
99  if (m_useBackgroundLevel > 0
100  and m_energyCutBkgd[0] < m_energyCutBkgd[1])
101  B2FATAL("ECLCRFinderModule::initialize(): m_energyCutBkgd[0] must be larger than m_energyCutBkgd[1].");
102  if (m_useBackgroundLevel > 0
103  and m_energyCutBkgd[1] < m_energyCutBkgd[2])
104  B2FATAL("ECLCRFinderModule::initialize(): m_energyCutBkgd[1] must be larger than m_energyCutBkgd[2].");
105  if (m_useBackgroundLevel > 0
106  and m_energyCutBkgd[0] < m_energyCutBkgd[2])
107  B2FATAL("ECLCRFinderModule::initialize(): m_energyCutBkgd[0] must be larger than m_energyCutBkgd[2].");
108  if (m_useBackgroundLevel > 0
109  and m_energyCut[0] > m_energyCutBkgd[0])
110  B2FATAL("ECLCRFinderModule::initialize(): m_energyCut[0] must be smaller than m_energyCutBkgd[0].");
111  if (m_useBackgroundLevel > 0
112  and m_energyCut[1] > m_energyCutBkgd[1])
113  B2FATAL("ECLCRFinderModule::initialize(): m_energyCut[1] must be smaller than m_energyCutBkgd[1].");
114  if (m_useBackgroundLevel > 0
115  and m_energyCut[2] > m_energyCutBkgd[2])
116  B2FATAL("ECLCRFinderModule::initialize(): m_energyCut[2] must be smaller than m_energyCutBkgd[2].");
117 
118  // Initialize neighbour maps.
119  m_neighbourMaps.resize(2);
122 
123  // Initialize the modified energy cuts (that could depend on event-by-event backgrounds later).
124  for (int i = 0; i < 3; i++) {
125  m_energyCutMod[i] = m_energyCut[i];
126  }
127 
128  // Resize the vectors
129  m_cellIdToSeedVec.resize(8737);
130  m_cellIdToGrowthVec.resize(8737);
131  m_cellIdToDigitVec.resize(8737);
132  m_cellIdToTempCRIdVec.resize(8737);
133  m_calDigitStoreArrPosition.resize(8737);
134 
135 }
136 
138 {
139  ;
140 }
141 
143 {
144  B2DEBUG(200, "ECLCRFinderModule::event()");
145 
146  // Reset the vector(s).
147  memset(&m_cellIdToSeedVec[0], 0, m_cellIdToSeedVec.size() * sizeof m_cellIdToSeedVec[0]);
148  memset(&m_cellIdToGrowthVec[0], 0, m_cellIdToGrowthVec.size() * sizeof m_cellIdToGrowthVec[0]);
149  memset(&m_cellIdToDigitVec[0], 0, m_cellIdToDigitVec.size() * sizeof m_cellIdToDigitVec[0]);
150  memset(&m_cellIdToTempCRIdVec[0], 0, m_cellIdToTempCRIdVec.size() * sizeof m_cellIdToTempCRIdVec[0]);
151 
152  // Fill a vector that can be used to map cellid -> store array position
154  for (int i = 0; i < m_eclCalDigits.getEntries(); i++) {
155  m_calDigitStoreArrPosition[m_eclCalDigits[i]->getCellId()] = i;
156  }
157 
158  // Clear the map(s).
159  m_cellIdToTempCRIdMap.clear();
160 
161  // Init variables.
162  m_tempCRId = 1;
163 
164  //-------------------------------------------------------
165  // Get background level for this events and adjust cuts.
166  if (m_useBackgroundLevel > 0) {
167  const int bkgdcount = m_eventLevelClusteringInfo->getNECLCalDigitsOutOfTime();
168 
169  // This scaling can probably be more clever to be really efficienct.
170  // So far just scale linearly between 0 and 280 (release-07).
171  double frac = 1.0;
172  if (m_fullBkgdCount > 0) frac = static_cast<double>(bkgdcount) / static_cast<double>(m_fullBkgdCount);
173 
174  B2DEBUG(175, "ECLCRFinderModule::event(), Background count for this event: " << bkgdcount << " (expected for full bkgd: " <<
175  m_fullBkgdCount << ", scaling factor is " << frac << ".");
176 
177  // Scale cut values.
178  for (int i = 0; i < 3; i++) {
179  m_energyCutMod[i] = m_energyCut[i] + (m_energyCutBkgd[i] - m_energyCut[i]) * frac;
180  B2DEBUG(200, "ECLCRFinderModule::event(), Energy cut value m_energyCutMod[" << i << "] = " << m_energyCutMod[i] <<
181  ", without bkgd scale m_energyCut[" << i << "] = " << m_energyCut[i]);
182  }
183  }
184 
185  //-------------------------------------------------------
186  // fill digits into maps
187  for (const auto& eclCalDigit : m_eclCalDigits) {
188  const double energy = eclCalDigit.getEnergy();
189  const double time = eclCalDigit.getTime();
190  const double timeresolution = eclCalDigit.getTimeResolution();
191  const int cellid = eclCalDigit.getCellId();
192  const bool fitfailed = eclCalDigit.isFailedFit();
193 
194  double timeresidual = 999.;
195  if (!fitfailed and fabs(timeresolution) > 1e-9) {
196  timeresidual = time / timeresolution;
197  }
198 
199  // Negative timecut is interpreted as cut on time residual, positive cut as cut on the timeresolution!
200  // Fill seed crystals to a map.
201  unsigned isSeed = 0;
202  if (energy >= m_energyCutMod[0]) {
203  if (fitfailed > 0 and m_skipFailedTimeFitDigits > 0) continue;
204  if (!fitfailed) {
205  if (m_timeCut[0] > 1e-9 and fabs(timeresolution) > m_timeCut[0]) continue;
206  if (m_timeCut[0] < -1e-9 and fabs(timeresidual) > fabs(m_timeCut[0])) continue;
207  }
208 
209  m_cellIdToSeedVec[cellid] = 1;
210  isSeed = 1;
211  B2DEBUG(250, "ECLCRFinderModule::event(), adding 'seed digit' with cellid = " << cellid);
212  }
213 
214  // Fill growth crystals to a map.
215  unsigned isGrowth = 0;
216  if (energy >= m_energyCutMod[1]) {
217  if (isSeed == 0) { // if a cell is a seed, it is also a growth cell (e.g. for different timing cuts)
218  if (fitfailed > 0 and m_skipFailedTimeFitDigits > 0) continue;
219  if (!fitfailed) {
220  if (m_timeCut[1] > 1e-9 and fabs(timeresolution) > m_timeCut[1]) continue;
221  if (m_timeCut[1] < -1e-9 and fabs(timeresidual) > fabs(m_timeCut[1])) continue;
222  }
223  }
224 
225  m_cellIdToGrowthVec[cellid] = 1;
226  isGrowth = 1;
227  B2DEBUG(250, "ECLCRFinderModule::event(), adding 'growth digit' with cellid = " << cellid);
228  }
229 
230  // Fill all crystals above threshold to a map (this must include growth and seed crystals!).
231  if (energy >= m_energyCutMod[2]) {
232  if (isGrowth == 0) { // if a cell is a growth (incl. seed), it is also a growth cell (e.g. for different timing cuts)
233  if (fitfailed > 0 and m_skipFailedTimeFitDigits > 0) continue;
234  if (!fitfailed) {
235  if (m_timeCut[2] > 1e-9 and fabs(timeresolution) > m_timeCut[2]) continue;
236  if (m_timeCut[2] < -1e-9 and fabs(timeresidual) > fabs(m_timeCut[2])) continue;
237  }
238  }
239 
240  m_cellIdToDigitVec[cellid] = 1;
241  B2DEBUG(250, "ECLCRFinderModule::event(), adding 'digit' with cellid = " << cellid);
242  }
243 
244  } // done filling digit map
245 
246  //-------------------------------------------------------
247  // 'find" in a map is faster if the number of seeds is not too large, can be replaced easily once we know what seed cuts we want.
248  for (unsigned int pos = 1; pos < m_cellIdToSeedVec.size(); ++pos) {
249  if (m_cellIdToSeedVec[pos] > 0) {
250  checkNeighbours(pos, m_tempCRId, 0);
251  ++m_tempCRId; // This is just a number, will be replaced by a consecutive number later in this module
252  }
253  }
254 
255  //-------------------------------------------------------
256  // Make CR Ids consecutive.
257  std::map< int, int > tempCRIdToCRIdMap;
258  std::map< int, int>::iterator tempCRIdToCRIdMapIterator;
259 
260  int CRId = 1;
261  for (unsigned int i = 1; i < m_cellIdToTempCRIdVec.size(); ++i) {
262 
263  if (m_cellIdToTempCRIdVec[i] > 0) { // digit belongs to a temporary CR
264  tempCRIdToCRIdMapIterator = tempCRIdToCRIdMap.find(m_cellIdToTempCRIdVec[i]);
265 
266  if (tempCRIdToCRIdMapIterator == tempCRIdToCRIdMap.end()) { // not found
267  tempCRIdToCRIdMap[m_cellIdToTempCRIdVec[i]] = CRId;
268  ++CRId;
269  }
270  }
271  }
272 
273  // Create CRs and add relations to digits.
274  for (const auto& entry : tempCRIdToCRIdMap) {
275  int connectedRegionID = entry.second;
276 
277  // create CR
278 
279  // Append to store array.
280  const auto aCR = m_eclConnectedRegions.appendNew();
281 
282  // Fill variable(s).
283  aCR->setCRId(connectedRegionID);
284 
285  // Add relations to all digits in this CR.
286  for (unsigned int i = 1; i < m_cellIdToTempCRIdVec.size(); ++i) {
287  if (tempCRIdToCRIdMap[m_cellIdToTempCRIdVec[i]] == connectedRegionID) {
288 
289  const int pos = m_calDigitStoreArrPosition[i];
290  aCR->addRelationTo(m_eclCalDigits[pos], 1.0);
291  }
292  }
293  } // end m_cellIdToTempCRIdVec loop
294 }
295 
296 
298 {
299  B2DEBUG(200, "ECLCRFinderModule::endRun()");
300 }
301 
302 
304 {
305  B2DEBUG(200, "ECLCRFinderModule::terminate()");
306  for (unsigned int i = 0; i < m_neighbourMaps.size(); i++) {
307  if (m_neighbourMaps[i]) delete m_neighbourMaps[i];
308  }
309 
310 }
311 
312 
313 void ECLCRFinderModule::checkNeighbours(const int cellid, const int tempcrid, const int type)
314 {
315  B2DEBUG(200, "ECLCRFinderModule::checkNeighbours() type=" << type);
316 
317  for (const auto& neighbour : m_neighbourMaps[type]->getNeighbours(cellid)) {
318  B2DEBUG(200, "ECLCRFinderModule::checkNeighbours(): neighbour=" << neighbour);
319 
320  // Check if this digit is above the lowest threshold (i.e. included in m_cellIdToDigitPointerVec) to be added.
321  int isAdded = 0;
322  if (m_cellIdToDigitVec[neighbour] > 0) {
323  updateCRs(neighbour, tempcrid);
324  isAdded = 1;
325  }
326 
327  // Check if we have to grow further.
328  if (m_cellIdToGrowthVec[neighbour] > 0) {
329 
330  if (isAdded < 1) {
331  updateCRs(neighbour, tempcrid); // it could be that this digit is not in the all digit list (eg. tight timing cuts for "all digits".
332  isAdded = 1;
333  }
334 
335  if (m_cellIdToTempCRIdVec[neighbour] == 0) { //found
336  checkNeighbours(neighbour, tempcrid, 1);
337  }
338  }
339  }
340 }
341 
342 
343 void ECLCRFinderModule::updateCRs(int cellid, int tempcr)
344 {
345  B2DEBUG(200, "ECLCRFinderModule::updateCRs()");
346 
347  // Check if this cellid already belongs to a connected region.
348  int thiscr = m_cellIdToTempCRIdVec[cellid];
349 
350  if (thiscr != 0) {
351 
352  // This cellid is already in another connected region, update all cells of this other connected region
353  for (unsigned int i = 1; i < m_cellIdToTempCRIdVec.size(); ++i) {
354  if (m_cellIdToTempCRIdVec[i] == thiscr) {
355  m_cellIdToTempCRIdVec[i] = tempcr;
356  }
357  }
358 
359  } else { //not in a CR yet, add it!
360  m_cellIdToTempCRIdVec[cellid] = tempcr;
361  }
362 }
Belle2::ECLCRFinderModule::event
virtual void event() override
Event.
Definition: ECLCRFinderModule.cc:142
REG_MODULE
#define REG_MODULE(moduleName)
Register the given module (without 'Module' suffix) with the framework.
Definition: Module.h:652
Belle2::ECLCRFinderModule::beginRun
virtual void beginRun() override
Begin.
Definition: ECLCRFinderModule.cc:137
Belle2::ECLCRFinderModule::m_eclConnectedRegions
StoreArray< ECLConnectedRegion > m_eclConnectedRegions
Store array: ECLConnectedRegion.
Definition: ECLCRFinderModule.h:89
Belle2::ECLCRFinderModule::m_energyCut
double m_energyCut[3]
Energy cut for seed, neighbours, ...
Definition: ECLCRFinderModule.h:109
Belle2::ECLCRFinderModule::~ECLCRFinderModule
virtual ~ECLCRFinderModule()
Destructor.
Definition: ECLCRFinderModule.cc:78
Belle2::ECLCRFinderModule::m_cellIdToTempCRIdVec
std::vector< int > m_cellIdToTempCRIdVec
Connected Region map.
Definition: ECLCRFinderModule.h:133
Belle2::ECLCRFinderModule::m_energyCutBkgd
double m_energyCutBkgd[3]
Energy cut (for high background) for seed, neighbours, ...
Definition: ECLCRFinderModule.h:110
Belle2::ECLCRFinderModule::m_tempCRId
int m_tempCRId
Temporary CR ID.
Definition: ECLCRFinderModule.h:120
Belle2::ECLCRFinderModule::m_timeCut
double m_timeCut[3]
Time cut for seed, neighbours, ...
Definition: ECLCRFinderModule.h:111
Belle2::ECLCRFinderModule::updateCRs
void updateCRs(int cellid, int tempcr)
Update CRs.
Definition: ECLCRFinderModule.cc:343
Belle2::Module
Base class for Modules.
Definition: Module.h:74
Belle2::Unit::MeV
static const double MeV
[megaelectronvolt]
Definition: Unit.h:124
Belle2::ECLCRFinderModule::m_mapType
std::string m_mapType[2]
Neighbour map types.
Definition: ECLCRFinderModule.h:112
Belle2::ECLCRFinderModule::m_cellIdToTempCRIdMap
std::map< int, int > m_cellIdToTempCRIdMap
cellid -> temporary CR.
Definition: ECLCRFinderModule.h:134
Belle2::ECL::ECLNeighbours
Class to get the neighbours for a given cell id.
Definition: ECLNeighbours.h:38
Belle2::ECLCRFinderModule::eventLevelClusteringInfoName
virtual const char * eventLevelClusteringInfoName() const
Name to be used for default option: EventLevelClusteringInfo.
Definition: ECLCRFinderModule.h:103
Belle2::ECLCRFinderModule::terminate
virtual void terminate() override
Terminate (close ROOT files here if you have opened any).
Definition: ECLCRFinderModule.cc:303
Belle2::ECLCRFinderModule::m_eclCalDigits
StoreArray< ECLCalDigit > m_eclCalDigits
Store array: ECLCalDigit.
Definition: ECLCRFinderModule.h:86
Belle2
Abstract base class for different kinds of events.
Definition: MillepedeAlgorithm.h:19
Belle2::ECLCRFinderModule::initialize
virtual void initialize() override
Initialize.
Definition: ECLCRFinderModule.cc:83
Belle2::ECLCRFinderModule::m_cellIdToDigitVec
std::vector< int > m_cellIdToDigitVec
cellid -> above threshold digits.
Definition: ECLCRFinderModule.h:125
Belle2::ECLCRFinderModule::m_useBackgroundLevel
int m_useBackgroundLevel
Background dependend energy and timing cuts.
Definition: ECLCRFinderModule.h:114
Belle2::ECLCRFinderModule::m_eventLevelClusteringInfo
StoreObjPtr< EventLevelClusteringInfo > m_eventLevelClusteringInfo
Store object pointer: EventLevelClusteringInfo.
Definition: ECLCRFinderModule.h:92
Belle2::ECLCRFinderModule::endRun
virtual void endRun() override
End run.
Definition: ECLCRFinderModule.cc:297
Belle2::ECLCRFinderModule::checkNeighbours
void checkNeighbours(const int cellid, const int tempcrid, const int type)
Neighbour finder.
Definition: ECLCRFinderModule.cc:313
Belle2::ECLCRFinderModule::m_cellIdToGrowthVec
std::vector< int > m_cellIdToGrowthVec
cellid -> growth digits.
Definition: ECLCRFinderModule.h:124
Belle2::ECLCRFinderModule::m_energyCutMod
double m_energyCutMod[3]
Other variables.
Definition: ECLCRFinderModule.h:119
Belle2::ECLCRFinderModule::m_neighbourMaps
std::vector< ECL::ECLNeighbours * > m_neighbourMaps
Neighbour maps.
Definition: ECLCRFinderModule.h:137
Belle2::ECLCRFinderModule::m_mapPar
double m_mapPar[2]
Parameters for neighbour maps.
Definition: ECLCRFinderModule.h:113
Belle2::ECLCRFinderModule::eclConnectedRegionArrayName
virtual const char * eclConnectedRegionArrayName() const
Name to be used for default option: ECLConnectedRegions.
Definition: ECLCRFinderModule.h:99
Belle2::ECLCRFinderModule::eclCalDigitArrayName
virtual const char * eclCalDigitArrayName() const
Name to be used for default or PureCsI option: ECLCalDigits.
Definition: ECLCRFinderModule.h:95
Belle2::ECLCRFinderModule
Class to find connected regions.
Definition: ECLCRFinderModule.h:61
Belle2::ECLCRFinderModule::m_fullBkgdCount
int m_fullBkgdCount
Number of expected background digits at full background.
Definition: ECLCRFinderModule.h:116
Belle2::ECLCRFinderModule::m_cellIdToSeedVec
std::vector< int > m_cellIdToSeedVec
Digit vectors.
Definition: ECLCRFinderModule.h:123
Belle2::ECLCRFinderModule::m_calDigitStoreArrPosition
std::vector< int > m_calDigitStoreArrPosition
vector (8736+1 entries) with cell id to store array positions
Definition: ECLCRFinderModule.h:128
Belle2::ECLCRFinderModule::m_skipFailedTimeFitDigits
int m_skipFailedTimeFitDigits
Handling of digits with failed time fits.
Definition: ECLCRFinderModule.h:115