Belle II Software  release-06-02-00
ECLTRGInformationModule.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 //This module
9 #include <ecl/modules/eclTRGInformation/ECLTRGInformationModule.h>
10 
11 //Framework
12 #include <framework/logging/Logger.h>
13 #include <framework/gearbox/Unit.h>
14 
15 //ECL
16 #include <ecl/dataobjects/ECLCalDigit.h>
17 
18 //MDST
19 #include <mdst/dataobjects/ECLCluster.h>
20 
21 //TRG
22 #include <trg/ecl/dataobjects/TRGECLUnpackerStore.h>
23 #include <trg/ecl/dataobjects/TRGECLUnpackerEvtStore.h>
24 
25 #include <trg/ecl/TrgEclMapping.h>
26 
27 //Analysis
28 #include <analysis/dataobjects/ECLTRGInformation.h>
29 #include <analysis/dataobjects/ECLTriggerCell.h>
30 
31 using namespace Belle2;
32 using namespace std;
33 
34 //-----------------------------------------------------------------
35 // Register the Module
36 //-----------------------------------------------------------------
38 
39 //-----------------------------------------------------------------
40 // Implementation
41 //-----------------------------------------------------------------
42 
44 {
45  // Set module properties
46  setDescription("Get ECL TRG energy information");
47  addParam("clusterEnergyThreshold", m_clusterEnergyThreshold, "Include ECLClusters above this energy in the energy sum.",
48  100.0 * Belle2::Unit::MeV);
49 
50  setPropertyFlags(c_ParallelProcessingCertified);
51 }
52 
54 {
56  m_eclCalDigits.isRequired();
57  m_eclClusters.isRequired();
58  m_trgUnpackerStore.isRequired();
59  m_trgUnpackerEvtStore.isRequired();
60 
62  m_eclTRGInformation.registerInDataStore();
63  m_eclTCs.registerInDataStore();
64 
66  m_eclClusters.registerRelationTo(m_eclTCs);
67  m_eclTCs.registerRelationTo(m_eclCalDigits);
68 
70  m_calDigitStoreArrPosition.resize(8736 + 1);
71  m_TCStoreArrPosition.resize(ECLTRGInformation::c_nTCs + 1);
72 
74  m_trgmap = new TrgEclMapping();
75 }
76 
78 {
79  // Fill a vector that can be used to map cellid -> store array position. Dont resize!
80  memset(&m_calDigitStoreArrPosition[0], -1, m_calDigitStoreArrPosition.size() * sizeof m_calDigitStoreArrPosition[0]);
81  for (int i = 0; i < m_eclCalDigits.getEntries(); i++) {
82  m_calDigitStoreArrPosition[m_eclCalDigits[i]->getCellId()] = i;
83  }
84 
85  int EventTiming = 0;
86  int RevoGDL = 0; // L1 Revo clk (Same value in an evnet)
87  int RevoFAM = 0; // FAM Revo clk (Same value in an event)
88  for (const auto& trgEvt : m_trgUnpackerEvtStore) {
89  EventTiming = trgEvt.getEvtTime();
90  RevoGDL = trgEvt.getL1Revo();
91  RevoFAM = trgEvt.getEvtRevo();
92  }
93 
94  // Store each TC and set relations to ECLClusters
95  for (const auto& trg : m_trgUnpackerStore) {
96 
97  if (trg.getTCId()<1 or trg.getTCId()>ECLTRGInformation::c_nTCs) continue;
98 
99  const auto aTC = m_eclTCs.appendNew();
100 
101  const unsigned idx = trg.getTCId();
102 
103  aTC->setTCId(idx);
104  aTC->setFADC(trg.getTCEnergy());
105  aTC->setTiming(trg.getTCTime());
106  aTC->setEvtTiming(EventTiming);
107  aTC->setRevoGDL(RevoGDL);
108  aTC->setRevoFAM(RevoFAM);
109  aTC->setThetaId(m_trgmap->getTCThetaIdFromTCId(idx));
110  aTC->setPhiId(m_trgmap->getTCPhiIdFromTCId(idx));
111  aTC->setHitWin(trg.getHitWin());
112 
113  // Fill ECLCalDigit energy sum
114  float energySum = 0.;
115  for (const auto& id : m_trgmap->getXtalIdFromTCId(idx)) {
116  // m_trgmap returns fixed size vectors with '0' to indicate empty positions -> 1-based
117  if (id > 0) {
118  const int pos = m_calDigitStoreArrPosition[id]; // id is 1-based, m_calDigitStoreArrPosition is 1-based
119  if (pos >= 0) { //not existing digits would return -1
120  energySum += m_eclCalDigits[pos]->getEnergy();
121 
122  aTC->addRelationTo(m_eclCalDigits[pos]);
123  }
124  }
125  }
126 
127  aTC->setECLCalDigitEnergy(energySum);
128  }
129 
130  // Fill a vector that can be used to map tcid -> store array position. Dont resize!
131  memset(&m_TCStoreArrPosition[0], -1, m_TCStoreArrPosition.size() * sizeof m_TCStoreArrPosition[0]);
132  for (int i = 0; i < m_eclTCs.getEntries(); i++) {
133  m_TCStoreArrPosition[m_eclTCs[i]->getTCId()] = i;
134  if (m_eclTCs[i]->getTCId() == 0) {
135  B2ERROR(m_eclTCs[i]->getTCId() << " not possible");
136  }
137  }
138 
139  // need relation for ECLClusters
140  for (const auto& cluster : m_eclClusters) {
141 
142  // only photon clusters
143  if (!cluster.hasHypothesis(ECLCluster::EHypothesisBit::c_nPhotons)) continue;
144 
145  // map TCId, energy
146  tcmap TCMap;
147 
148  // loop over all digits of this cluster
149  auto relationsCalDigits = cluster.getRelationsTo<ECLCalDigit>();
150  for (unsigned int idx = 0; idx < relationsCalDigits.size(); ++idx) {
151  const auto cal = relationsCalDigits.object(idx);
152  const auto weight = relationsCalDigits.weight(idx);
153 
154  auto relationsTCs = cal->getRelationsWith<ECLTriggerCell>();
155  for (unsigned int idxTC = 0; idxTC < relationsTCs.size(); ++idxTC) {
156  const auto tc = relationsTCs.object(idxTC);
157 
158  const unsigned tcid = tc->getTCId();
159  TCMap[tcid] += weight * cal->getEnergy();
160  }
161  }
162 
163  // set weighted relations between cluster and TC, where the weight is the energy of ECLCalDigits that belong to this shower in this TC
164  for (const auto& mapentry : TCMap) {
165  const int pos = m_TCStoreArrPosition[mapentry.first];
166  cluster.addRelationTo(m_eclTCs[pos], mapentry.second);
167  }
168  }
169 
170  //energy sum
171  float sumEnergyTCECLCalDigitInECLCluster = 0.0;
172  float sumEnergyECLCalDigitInECLCluster = 0.0;
173 
174  // create the dataobject
175  if (!m_eclTRGInformation) {
176  m_eclTRGInformation.create();
177  }
178 
179  // get the actual TC information (energy, timing, ...)
180  float eventtiming = std::numeric_limits<float>::quiet_NaN();
181  int maxtcid = -1;
182  float maxtc = -1;
183 
184  for (const auto& trg : m_trgUnpackerStore) {
185  const int tcid = trg.getTCId();
186  if (tcid<1 or tcid>ECLTRGInformation::c_nTCs) continue;
187 
188  if (trg.getTCEnergy() > maxtc) {
189  maxtc = trg.getTCEnergy();
190  maxtcid = tcid;
191  }
192 
193  m_eclTRGInformation->setEnergyTC(tcid, trg.getTCEnergy());
194  m_eclTRGInformation->setTimingTC(tcid, trg.getTCTime());
195  m_eclTRGInformation->setRevoGDLTC(tcid, RevoGDL);
196  m_eclTRGInformation->setRevoFAMTC(tcid, RevoFAM);
197  m_eclTRGInformation->setHitWinTC(tcid, trg.getHitWin());
198 
199  if (trg.getTCEnergy() > 0 and std::isnan(eventtiming)) {
200  eventtiming = EventTiming;
201  }
202 
203  B2DEBUG(29, "TC Id: (1.." << ECLTRGInformation::c_nTCs << ") " << trg.getTCId() << " FADC=" << trg.getTCEnergy() << ", t=" <<
204  trg.getTCTime() << ", tevent=" << eventtiming);
205  }
206 
207  // loop over all possible TCs and fill the 'offline' ECLCalDigit information
208  for (unsigned idx = 1; idx <= ECLTRGInformation::c_nTCs; idx++) {
209  float energyInTC = 0.;
210  float energyInTCInECLCluster = 0.;
211  float highestEnergy = -1.;
212  float time = std::numeric_limits<float>::quiet_NaN();
213 
214  for (const auto& id : m_trgmap->getXtalIdFromTCId(idx)) {
215  // the mapping returns fixed size vectors with '0' to indicate empty positions
216  if (id > 0) {
217  const int pos = m_calDigitStoreArrPosition[id];
218 
219  if (pos >= 0) {
220  energyInTC += m_eclCalDigits[pos]->getEnergy();
221 
222  // check if that eclcaldigit is part of an ECLCluster above threshold
223  auto rel = m_eclCalDigits[pos]->getRelationsFrom<ECLCluster>();
224  for (unsigned int irel = 0; irel < rel.size(); ++irel) {
225 
226  const auto cluster = rel.object(irel);
227 
228  if (!cluster->hasHypothesis(ECLCluster::EHypothesisBit::c_nPhotons)) continue;
229 
230  const auto weight = rel.weight(irel);
231  float clusterenergy = cluster->getEnergy(ECLCluster::EHypothesisBit::c_nPhotons);
232 
233  B2DEBUG(28, irel << " " << clusterenergy << " " << m_clusterEnergyThreshold);
234 
235  if (clusterenergy >= m_clusterEnergyThreshold) {
236  energyInTCInECLCluster += weight * m_eclCalDigits[pos]->getEnergy();
237  }
238  }
239 
240  // get the highest energy caldigit for the approximate timing
241  if (m_eclCalDigits[pos]->getEnergy() > highestEnergy) {
242  highestEnergy = m_eclCalDigits[pos]->getEnergy();
243  time = m_eclCalDigits[pos]->getTime();
244  }
245  }
246  }
247  }
248 
249  // only add this to the total sum if the TC is read out and within trigger acceptance
250  if (m_eclTRGInformation->getEnergyTC(idx)) {
251  B2DEBUG(28, energyInTCInECLCluster << " " << m_trgmap->getTCThetaIdFromTCId(idx));
252  }
253 
254  if (m_trgmap->getTCThetaIdFromTCId(idx) >= 2 and
255  m_trgmap->getTCThetaIdFromTCId(idx) <= 15) {
256  if (m_eclTRGInformation->getEnergyTC(idx)) sumEnergyTCECLCalDigitInECLCluster += energyInTCInECLCluster;
257  sumEnergyECLCalDigitInECLCluster += energyInTCInECLCluster;
258  }
259 
260  m_eclTRGInformation->setEnergyTCECLCalDigit(idx, energyInTC);
261  m_eclTRGInformation->setTimingTCECLCalDigit(idx, time);
262 
263  m_eclTRGInformation->setThetaIdTC(idx, m_trgmap->getTCThetaIdFromTCId(idx));
264  m_eclTRGInformation->setPhiIdTC(idx, m_trgmap->getTCPhiIdFromTCId(idx));
265 
266  if (energyInTC > 0) B2DEBUG(29, "ECLCalDigits TC Id: (1.." << ECLTRGInformation::c_nTCs << ") " << idx << " E=" << energyInTC <<
267  ", t=" << time);
268 
269  }
270 
271  m_eclTRGInformation->setClusterEnergyThreshold(m_clusterEnergyThreshold);
272  m_eclTRGInformation->setSumEnergyTCECLCalDigitInECLCluster(sumEnergyTCECLCalDigitInECLCluster);
273  m_eclTRGInformation->setSumEnergyECLCalDigitInECLCluster(sumEnergyECLCalDigitInECLCluster);
274  m_eclTRGInformation->setEvtTiming(eventtiming);
275  m_eclTRGInformation->setMaximumTCId(maxtcid);
276 
277  //flag highest energy TC
278  if (maxtcid >= 0) {
279  int pos = m_TCStoreArrPosition[maxtcid];
280  m_eclTCs[pos]->setIsHighestFADC(true);
281  }
282 
283 }
284 
286 {
287  if (m_trgmap) delete m_trgmap;
288 }
Class to store calibrated ECLDigits: ECLCalDigits.
Definition: ECLCalDigit.h:23
ECL cluster data.
Definition: ECLCluster.h:27
@ c_nPhotons
CR is split into n photons (N1)
Module to get ECL TRG energy information.
virtual void initialize() override
initialize
virtual void event() override
event
virtual void terminate() override
terminate
std::map< unsigned, float > tcmap
map TCId, energy
Class to store information about ECL trigger cells (TCs)
static constexpr int c_nTCs
Number of TCs.
ECL Trigger cells.
unsigned int getTCId() const
Get m_TCId.
Base class for Modules.
Definition: Module.h:72
A class of TC Mapping.
Definition: TrgEclMapping.h:26
static const double MeV
[megaelectronvolt]
Definition: Unit.h:114
#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.