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