Project
Loading...
Searching...
No Matches
Clusterer.cxx
Go to the documentation of this file.
1// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3// All rights not expressly granted are reserved.
4//
5// This software is distributed under the terms of the GNU General Public
6// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7//
8// In applying this license CERN does not waive the privileges and immunities
9// granted to it by virtue of its status as an Intergovernmental Organization
10// or submit itself to any jurisdiction.
11
14#include <algorithm>
15#include <fairlogger/Logger.h> // for LOG
20#include <TStopwatch.h>
21
22using namespace o2::tof;
23
24//__________________________________________________
25void Clusterer::process(DataReader& reader, std::vector<Cluster>& clusters, MCLabelContainer const* digitMCTruth)
26{
27 TStopwatch timerProcess;
28 timerProcess.Start();
29
30 reader.init();
31 int totNumDigits = 0;
32
33 while (reader.getNextStripData(mStripData)) {
34 LOG(debug) << "TOFClusterer got Strip " << mStripData.stripID << " with Ndigits "
35 << mStripData.digits.size();
36 totNumDigits += mStripData.digits.size();
37
38 calibrateStrip();
39 processStrip(clusters, digitMCTruth);
40 }
41
42 LOG(debug) << "We had " << totNumDigits << " digits in this event";
43 timerProcess.Stop();
44}
45
46//__________________________________________________
47void Clusterer::calibrateStrip()
48{
49 // method to calibrate the times from the current strip
50
51 for (int idig = 0; idig < mStripData.digits.size(); idig++) {
52 // LOG(debug) << "Checking digit " << idig;
53 Digit* dig = &mStripData.digits[idig];
54 // LOG(info) << "channel = " << dig->getChannel();
55 dig->setBC(dig->getBC() - mBCOffset); // RS Don't use raw BC, always start from the beginning of the TF
56 double calib = mCalibApi->getTimeCalibration(dig->getChannel(), dig->getTOT() * Geo::TOTBIN_NS);
57 //printf("channel %d) isProblematic = %d, fractionUnderPeak = %f\n",dig->getChannel(),mCalibApi->isProblematic(dig->getChannel()),mCalibApi->getFractionUnderPeak(dig->getChannel())); // toberem
58 bool isProbOrError = mAreCalibStored ? mCalibApi->isChannelError(dig->getChannel()) || mCalibApi->isNoisy(dig->getChannel()) : mCalibApi->isChannelError(dig->getChannel()) || mCalibApi->isNoisy(dig->getChannel()) || mCalibApi->isProblematic(dig->getChannel());
59 dig->setIsProblematic(isProbOrError);
60 dig->setCalibratedTime(dig->getTDC() * Geo::TDCBIN + dig->getBC() * o2::constants::lhc::LHCBunchSpacingNS * 1E3 - Geo::LATENCYWINDOW * 1E3 - calib); //TODO: to be checked that "-" is correct, and we did not need "+" instead :-)
61 //printf("calibration correction = %f\n",calib); // toberem
62 }
63}
64
65//__________________________________________________
66void Clusterer::processStrip(std::vector<Cluster>& clusters, MCLabelContainer const* digitMCTruth)
67{
68 // method to clusterize the current strip
69
70 Int_t detId[5];
71 Int_t chan, chan2, chan3;
72 Int_t strip1, strip2;
73 Int_t iphi, iphi2, iphi3;
74 Int_t ieta, ieta2, ieta3; // it is the number of padz-row increasing along the various strips
75
76 for (int idig = 0; idig < mStripData.digits.size(); idig++) {
77 // LOG(debug) << "Checking digit " << idig;
78 Digit* dig = &mStripData.digits[idig];
79 //printf("checking digit %d - alreadyUsed=%d - problematic=%d\n",idig,dig->isUsedInCluster(),dig->isProblematic()); // toberem
80 if (dig->isUsedInCluster() || dig->isProblematic()) {
81 continue; // the digit was already used to build a cluster, or it was declared problematic
82 }
83
84 mNumberOfContributingDigits = 0;
85 dig->getPhiAndEtaIndex(iphi, ieta);
86 if (mStripData.digits.size() > 1) {
87 LOG(debug) << "idig = " << idig;
88 }
89
90 // first we make a cluster out of the digit
91 int noc = clusters.size();
92 // LOG(debug) << "noc = " << noc << "\n";
93 clusters.emplace_back();
94 Cluster& c = clusters[noc];
95 addContributingDigit(dig);
96 double timeDig = dig->getCalibratedTime();
97
98 for (int idigNext = idig + 1; idigNext < mStripData.digits.size(); idigNext++) {
99 Digit* digNext = &mStripData.digits[idigNext];
100 if (digNext->isUsedInCluster() || dig->isProblematic()) {
101 continue; // the digit was already used to build a cluster, or was problematic
102 }
103 // check if the TOF time are close enough to be merged; if not, it means that nothing else will contribute to the cluster (since digits are ordered in time)
104 double timeDigNext = digNext->getCalibratedTime(); // in ps
105 LOG(debug) << "Time difference = " << timeDigNext - timeDig;
106 if (timeDigNext - timeDig > mDeltaTforClustering /*in ps*/) { // to be change to 500 ps
107 break;
108 }
109 digNext->getPhiAndEtaIndex(iphi2, ieta2);
110
111 // check if the fired pad are close in space
112 LOG(debug) << "phi difference = " << iphi - iphi2;
113 LOG(debug) << "eta difference = " << ieta - ieta2;
114 if ((std::abs(iphi - iphi2) > 1) || (std::abs(ieta - ieta2) > 1)) {
115 continue;
116 }
117
118 // if we are here, the digit contributes to the cluster
119 addContributingDigit(digNext);
120
121 } // loop on the second digit
122
123 //printf("build cluster\n");
124 buildCluster(c, digitMCTruth); // toberem
125
126 } // loop on the first digit
127}
128//______________________________________________________________________
129void Clusterer::addContributingDigit(Digit* dig)
130{
131
132 // adding a digit to the array that stores the contributing ones
133
134 if (mNumberOfContributingDigits == 6) {
135 LOG(debug) << "The cluster has already 6 digits associated to it, we cannot add more; returning without doing anything";
136
137 int phi, eta;
138 for (int i = 0; i < mNumberOfContributingDigits; i++) {
139 mContributingDigit[i]->getPhiAndEtaIndex(phi, eta);
140 LOG(debug) << "digit already in " << i << ", channel = " << mContributingDigit[i]->getChannel() << ",phi,eta = (" << phi << "," << eta << "), TDC = " << mContributingDigit[i]->getTDC() << ", calibrated time = " << mContributingDigit[i]->getCalibratedTime();
141 }
142
143 dig->getPhiAndEtaIndex(phi, eta);
144 LOG(debug) << "skipped digit"
145 << ", channel = " << dig->getChannel() << ",phi,eta = (" << phi << "," << eta << "), TDC = " << dig->getTDC() << ", calibrated time = " << dig->getCalibratedTime();
146
147 dig->setIsUsedInCluster(); // flag is at used in any case
148
149 return;
150 }
151 mContributingDigit[mNumberOfContributingDigits] = dig;
152 mNumberOfContributingDigits++;
153 dig->setIsUsedInCluster();
154
155 return;
156}
157
158//_____________________________________________________________________
159void Clusterer::buildCluster(Cluster& c, MCLabelContainer const* digitMCTruth)
160{
161 static const float inv12 = 1. / 12.;
162
163 // here we finally build the cluster from all the digits contributing to it
164
165 Digit* temp;
166 for (int idig = 1; idig < mNumberOfContributingDigits; idig++) {
167 // the digit[0] will be the main one
168 if (mContributingDigit[idig]->getTOT() > mContributingDigit[0]->getTOT()) {
169 temp = mContributingDigit[0];
170 mContributingDigit[0] = mContributingDigit[idig];
171 mContributingDigit[idig] = temp;
172 }
173 }
174
175 c.setMainContributingChannel(mContributingDigit[0]->getChannel());
176 c.setTgeant(mContributingDigit[0]->getTgeant());
177 c.setT0true(mContributingDigit[0]->getT0true());
178 c.setTime(mContributingDigit[0]->getCalibratedTime()); // time in ps (for now we assume it calibrated)
179 c.setTimeRaw(mContributingDigit[0]->getTDC() * Geo::TDCBIN + mContributingDigit[0]->getBC() * o2::constants::lhc::LHCBunchSpacingNS * 1E3); // time in ps (for now we assume it calibrated)
180
181 //printf("timeraw= %lf - time real = %lf (%d, %lu) \n",c.getTimeRaw(),mContributingDigit[0]->getTDC() * Geo::TDCBIN + mContributingDigit[0]->getBC() * o2::constants::lhc::LHCBunchSpacingNS * 1E3,mContributingDigit[0]->getTDC(),mContributingDigit[0]->getBC());
182
183 c.setTot(mContributingDigit[0]->getTOT() * Geo::TOTBIN_NS); // TOT in ns (for now we assume it calibrated)
184 //setL0L1Latency(); // to be filled (maybe)
185 //setDeltaBC(); // to be filled (maybe)
186
187 c.setDigitInfo(0, mContributingDigit[0]->getChannel(), mContributingDigit[0]->getCalibratedTime(), mContributingDigit[0]->getTOT() * Geo::TOTBIN_NS);
188
189 int ch1 = mContributingDigit[0]->getChannel();
190 short tot1 = mContributingDigit[0]->getTOT() < 20000 ? mContributingDigit[0]->getTOT() : 20000;
191 double dtime = c.getTimeRaw();
192
193 int chan1, chan2;
194 int phi1, phi2;
195 int eta1, eta2;
196 int deltaPhi, deltaEta;
197 int mask;
198
199 mContributingDigit[0]->getPhiAndEtaIndex(phi1, eta1);
200 // now set the mask with the secondary digits
201 for (int idig = 1; idig < mNumberOfContributingDigits; idig++) {
202 mContributingDigit[idig]->getPhiAndEtaIndex(phi2, eta2);
203 deltaPhi = phi1 - phi2;
204 deltaEta = eta1 - eta2;
205
206 bool isOk = true;
207
208 if (deltaPhi == 1) { // the digit is to the LEFT of the cluster; let's check about UP/DOWN/Same Line
209 if (deltaEta == 1) { // the digit is DOWN LEFT wrt the cluster
211 } else if (deltaEta == -1) { // the digit is UP LEFT wrt the cluster
213 } else { // the digit is LEFT wrt the cluster
215 }
216 } else if (deltaPhi == -1) { // the digit is to the RIGHT of the cluster; let's check about UP/DOWN/Same Line
217 if (deltaEta == 1) { // the digit is DOWN RIGHT wrt the cluster
219 } else if (deltaEta == -1) { // the digit is UP RIGHT wrt the cluster
221 } else { // the digit is RIGHT wrt the cluster
223 }
224 } else if (deltaPhi == 0) { // the digit is on the same column as the cluster; is it UP or Down?
225 if (deltaEta == 1) { // the digit is DOWN wrt the cluster
227 } else if (deltaEta == -1) { // the digit is UP wrt the cluster
229 } else { // same channel!
230 LOG(debug) << " Check what is going on, the digit you are trying to merge to the cluster must be in a different channels... ";
231 }
232 } else { // |delataphi| > 1
233 isOk = false;
234 mContributingDigit[idig]->setIsUsedInCluster(false);
235 }
236
237 if (isOk) {
238 c.setDigitInfo(c.getNumOfContributingChannels(), mContributingDigit[idig]->getChannel(), mContributingDigit[idig]->getCalibratedTime(), mContributingDigit[idig]->getTOT() * Geo::TOTBIN_NS);
239 c.addBitInContributingChannels(mask);
240
241 if (mCalibFromCluster && c.getNumOfContributingChannels() == 2 && !mIsNoisy[mContributingDigit[idig]->getChannel()] && !mIsNoisy[ch1]) { // fill info for calibration excluding noisy channels
242 int8_t dch = int8_t(mContributingDigit[idig]->getChannel() - ch1);
243 short tot2 = mContributingDigit[idig]->getTOT() < 20000 ? mContributingDigit[idig]->getTOT() : 20000;
244 dtime -= mContributingDigit[idig]->getTDC() * Geo::TDCBIN + mContributingDigit[idig]->getBC() * o2::constants::lhc::LHCBunchSpacingNS * 1E3;
245 addCalibFromCluster(ch1, dch, float(dtime), tot1, tot2);
246 }
247 }
248 }
249
250 // filling the MC labels of this cluster; the first will be those of the main digit; then the others
251 if (digitMCTruth != nullptr) {
252 int lbl = mClsLabels->getIndexedSize(); // this should correspond to the number of digits also;
253 //printf("lbl = %d\n", lbl);
254 for (int i = 0; i < mNumberOfContributingDigits; i++) {
255 if (!mContributingDigit[i]->isUsedInCluster()) {
256 continue;
257 }
258 //printf("contributing digit = %d\n", i);
259 int digitLabel = mContributingDigit[i]->getLabel();
260 //printf("digitLabel = %d\n", digitLabel);
261 gsl::span<const o2::MCCompLabel> mcArray = digitMCTruth->getLabels(digitLabel);
262 for (int j = 0; j < static_cast<int>(mcArray.size()); j++) {
263 //printf("checking element %d in the array of labels\n", j);
264 auto label = digitMCTruth->getElement(digitMCTruth->getMCTruthHeader(digitLabel).index + j);
265 //printf("EventID = %d\n", label.getEventID());
266 mClsLabels->addElement(lbl, label);
267 }
268 }
269 }
270
271 // set geometrical variables
272 int det[5];
273 Geo::getVolumeIndices(c.getMainContributingChannel(), det);
274 float pos[3];
275 Geo::getPos(det, pos);
276 Geo::rotateToSector(pos, c.getSector());
277 c.setXYZ(pos[2], pos[0], pos[1]); // storing coordinates in sector frame: note that the rotation above puts z in pos[1], the radial coordinate in pos[2], and the tangent coordinate in pos[0] (this is to match the TOF residual system, where we don't use the radial component), so we swap their positions.
278
279 c.setR(std::sqrt(pos[0] * pos[0] + pos[1] * pos[1])); // it is the R in the sector frame
280 c.setPhi(std::atan2(pos[1], pos[0]));
281
282 float errY2 = Geo::XPAD * Geo::XPAD * inv12;
283 float errZ2 = Geo::ZPAD * Geo::ZPAD * inv12;
284 float errYZ = 0;
285
286 //if(c.getNumOfContributingChannels() > 1){
287 // set errors according to a model not yet defined!
288 // TO DO
289 //}
290 c.setErrors(errY2, errZ2, errYZ);
291
292 return;
293}
294
295//_____________________________________________________________________
296void Clusterer::setFirstOrbit(uint64_t orb)
297{
298 mFirstOrbit = orb;
299 mBCOffset = orb * o2::constants::lhc::LHCMaxBunches;
300}
301//_____________________________________________________________________
302void Clusterer::addCalibFromCluster(int ch1, int8_t dch, float dtime, short tot1, short tot2)
303{
304 mCalibInfosFromCluster.emplace_back(ch1, dch, dtime, tot1, tot2);
305}
Definition of the TOF cluster.
uint16_t getBC() const
int32_t i
Definition of a container to keep Monte Carlo truth external to simulation objects.
uint16_t pos
Definition RawData.h:3
uint32_t j
Definition RawData.h:0
uint32_t c
Definition RawData.h:2
Definition of the TOF cluster finder.
std::ostringstream debug
gsl::span< TruthElement > getLabels(uint32_t dataindex)
TruthElement const & getElement(uint32_t elementindex) const
void addElement(uint32_t dataindex, TruthElement const &element, bool noElement=false)
MCTruthHeaderElement const & getMCTruthHeader(uint32_t dataindex) const
bool isChannelError(int channel) const
bool isNoisy(int ich)
bool isProblematic(int ich)
float getTimeCalibration(int ich, float tot) const
Cluster class for TOF.
Definition Cluster.h:37
void addCalibFromCluster(int ch1, int8_t dch, float dtime, short tot1, short tot2)
void setFirstOrbit(uint64_t orb)
void process(DataReader &r, std::vector< Cluster > &clusters, MCLabelContainer const *digitMCTruth)
Definition Clusterer.cxx:25
DataReader class for TOF.
Definition DataReader.h:28
virtual Bool_t getNextStripData(StripData &stripData)=0
virtual void init()=0
TOF digit implementation.
Definition Digit.h:31
uint64_t getBC() const
Definition Digit.h:58
void setBC(uint64_t bc)
Definition Digit.h:59
Int_t getLabel() const
Definition Digit.h:64
uint16_t getTOT() const
Definition Digit.h:55
void setTgeant(float val)
Definition Digit.h:97
bool isProblematic() const
Definition Digit.h:89
double getCalibratedTime() const
Definition Digit.h:86
Int_t getChannel() const
Definition Digit.h:49
void setIsUsedInCluster(bool val=true)
Definition Digit.h:75
void getPhiAndEtaIndex(int &phi, int &eta) const
Definition Digit.cxx:64
void setCalibratedTime(Double_t time)
Definition Digit.h:85
void setIsProblematic(bool flag)
Definition Digit.h:88
uint16_t getTDC() const
Definition Digit.h:52
Bool_t isUsedInCluster() const
Definition Digit.h:73
static constexpr Float_t ZPAD
Definition Geo.h:141
static constexpr Float_t XPAD
Definition Geo.h:139
static void rotateToSector(Float_t *xyz, Int_t isector)
Definition Geo.cxx:1028
static void getPos(Int_t *det, Float_t *pos)
Definition Geo.cxx:491
static void getVolumeIndices(Int_t index, Int_t *detId)
Definition Geo.cxx:543
static constexpr Float_t TOTBIN_NS
Definition Geo.h:154
static constexpr Float_t TDCBIN
TDC bin width [ps].
Definition Geo.h:150
static constexpr Double_t LATENCYWINDOW
Definition Geo.h:176
GLuint GLsizei const GLchar * label
Definition glcorearb.h:2519
GLint GLuint mask
Definition glcorearb.h:291
bool isOk(ResultWas::OfType resultType)
constexpr int LHCMaxBunches
constexpr double LHCBunchSpacingNS
return((dphi< 0 &&dphi > -constants::math::PI)||dphi > constants::math::PI) ? true T phi1
std::vector< Digit > digits
Definition DataReader.h:34
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"
std::vector< Cluster > clusters