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