Project
Loading...
Searching...
No Matches
PulseHeight.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
18#include <fairlogger/Logger.h>
19
20using namespace o2::trd;
21using namespace o2::trd::constants;
22
24{
25 mPHValues.clear();
26 mDistances.clear();
27}
28
30{
31}
32
34{
35 mOutFile = std::make_unique<TFile>("trd_PH.root", "RECREATE");
36 if (mOutFile->IsZombie()) {
37 LOG(error) << "Failed to create output file!";
38 return;
39 }
40 mOutTree = std::make_unique<TTree>("ph", "Data points for PH histograms");
41 mOutTree->Branch("values", &mPHValuesPtr);
42 mOutTree->Branch("dist", &mDistancesPtr);
43 mWriteOutput = true;
44 LOG(info) << "Writing PH data points to local file trd_PH.root";
45}
46
48{
49 if (!mWriteOutput) {
50 return;
51 }
52 try {
53 mOutFile->cd();
54 mOutTree->Write();
55 mOutTree.reset();
56 mOutFile->Close();
57 mOutFile.reset();
58 } catch (std::exception const& e) {
59 LOG(error) << "Failed to write output file, reason: " << e.what();
60 }
61 mWriteOutput = false;
62}
63
64void PulseHeight::setInput(const o2::globaltracking::RecoContainer& input, gsl::span<const Digit>* digits)
65{
66 mTracksInITSTPCTRD = input.getITSTPCTRDTracks<TrackTRD>();
67 mTracksInTPCTRD = input.getTPCTRDTracks<TrackTRD>();
68 mTrackletsRaw = input.getTRDTracklets();
69 mTriggerRecords = input.getTRDTriggerRecords();
70 mTrackTriggerRecordsTPCTRD = input.getTPCTRDTriggers();
71 mTrackTriggerRecordsITSTPCTRD = input.getITSTPCTRDTriggers();
72 mDigits = digits;
73}
74
76{
77 LOGP(debug, "Processing {} tracklets and {} digits from {} triggers and {} ITS-TPC-TRD tracks and {} TPC-TRD tracks",
78 mTrackletsRaw.size(), mDigits->size(), mTriggerRecords.size(), mTracksInITSTPCTRD.size(), mTracksInTPCTRD.size());
79 if (mDigits->size() == 0) {
80 return;
81 }
82 size_t nTrkTrig[2] = {mTrackTriggerRecordsITSTPCTRD.size(), mTrackTriggerRecordsTPCTRD.size()};
83 int lastTrkTrig[2] = {0};
84 for (const auto& trig : mTriggerRecords) {
85 if (trig.getNumberOfDigits() == 0) {
86 continue;
87 }
88 for (int iTrackType = 0; iTrackType <= 1; ++iTrackType) {
89 const gsl::span<const TrackTRD>* tracks = (iTrackType == 0) ? &mTracksInITSTPCTRD : &mTracksInTPCTRD;
90 const gsl::span<const TrackTriggerRecord>* trackTriggers = (iTrackType == 0) ? &mTrackTriggerRecordsITSTPCTRD : &mTrackTriggerRecordsTPCTRD;
91 for (int iTrigTrack = lastTrkTrig[iTrackType]; iTrigTrack < nTrkTrig[iTrackType]; ++iTrigTrack) {
92 const auto& trigTrack = (*trackTriggers)[iTrigTrack];
93 if (trigTrack.getBCData().differenceInBC(trig.getBCData()) > 0) {
94 // aborting, since track trigger is later than digit trigger";
95 LOGP(debug, "Aborting, track trigger is too late");
96 break;
97 }
98 if (trigTrack.getBCData() != trig.getBCData()) {
99 // skipping, since track trigger earlier than digit trigger";
100 LOGP(debug, "Skipping, track trigger is too late");
101 ++lastTrkTrig[iTrackType];
102 continue;
103 }
104 if ((*tracks)[trigTrack.getFirstTrack()].hasPileUpInfo() && (*tracks)[trigTrack.getFirstTrack()].getPileUpTimeShiftMUS() < mParams.pileupCut) {
105 // rejecting triggers which are close to other collisions (avoid pile-up)
106 ++lastTrkTrig[iTrackType];
107 LOGP(debug, "Rececting trigger due to pileup of {}", (*tracks)[trigTrack.getFirstTrack()].getPileUpTimeShiftMUS());
108 break;
109 }
110 for (int iTrk = trigTrack.getFirstTrack(); iTrk < trigTrack.getFirstTrack() + trigTrack.getNumberOfTracks(); iTrk++) {
111 const auto& trk = (*tracks)[iTrk];
112 for (int iLayer = 0; iLayer < 6; iLayer++) {
113 int trkltIdx = trk.getTrackletIndex(iLayer);
114 if (trkltIdx < 0) {
115 continue;
116 }
117 findDigitsForTracklet(mTrackletsRaw[trkltIdx], trig, iTrackType);
118 }
119 }
120 }
121 }
122 }
123 if (mWriteOutput) {
124 mOutTree->Fill();
125 }
126}
127
129{
130 auto trkltDet = trklt.getDetector();
131 int iDigitFirst = trig.getFirstDigit();
132 int iDigitLast = trig.getFirstDigit() + trig.getNumberOfDigits();
133 for (int iDigit = iDigitFirst + 1; iDigit < iDigitLast - 1; ++iDigit) {
134 const auto& digit = (*mDigits)[iDigit];
135 if (digit.isSharedDigit()) {
136 continue; // avoid double-counting of the same digit
137 }
138 if (digit.getDetector() != trkltDet || digit.getPadRow() != trklt.getPadRow() || digit.getPadCol() != trklt.getPadCol(mApplyShift)) {
139 // for now we loose charge information from padrow-crossing tracklets (~15% of all tracklets)
140 continue;
141 }
142 int nNeighbours = 0;
143 bool left = false;
144 bool right = false;
145 const auto* digitLeft = &(*mDigits)[iDigit + 1];
146 const auto* digitRight = &(*mDigits)[iDigit - 1];
147 // due to shared digits the neighbouring element might still be in the same pad column
148 if (digitLeft->getPadCol() == digit.getPadCol() && iDigit < iDigitLast - 2) {
149 digitLeft = &(*mDigits)[iDigit + 2];
150 }
151 if (digitRight->getPadCol() == digit.getPadCol() && iDigit > iDigitFirst + 2) {
152 digitRight = &(*mDigits)[iDigit - 2];
153 }
154 LOG(debug) << "Central digit: " << digit;
155 LOG(debug) << "Left digit: " << *digitLeft;
156 LOG(debug) << "Right digit: " << *digitRight;
157 int direction = 0;
158 if (digitLeft->isNeighbour(digit)) {
159 ++nNeighbours;
160 left = true;
161 direction = digit.getPadCol() - digitLeft->getPadCol();
162 }
163 if (digitRight->isNeighbour(digit) && digit.getPadCol() - digitRight->getPadCol() != direction) {
164 ++nNeighbours;
165 right = true;
166 }
167 if (nNeighbours > 0) {
168 int digitTrackletDistance = 0;
169 auto adcSumMax = digit.getADCsum();
170 if (left && digitLeft->getADCsum() > adcSumMax) {
171 adcSumMax = digitLeft->getADCsum();
172 digitTrackletDistance = 1;
173 }
174 if (right && digitRight->getADCsum() > adcSumMax) {
175 adcSumMax = digitRight->getADCsum();
176 digitTrackletDistance = -1;
177 }
178 mDistances.push_back(digitTrackletDistance);
179 for (int iTb = 0; iTb < TIMEBINS; ++iTb) {
180 uint16_t phVal = digit.getADC()[iTb];
181 if (left) {
182 phVal += digitLeft->getADC()[iTb];
183 }
184 if (right) {
185 phVal += digitRight->getADC()[iTb];
186 }
187 mPHValues.emplace_back(phVal, trkltDet, iTb, nNeighbours, type);
188 }
189 }
190 }
191}
Wrapper container for different reconstructed object types.
Global TRD definitions and constants.
Creates PH spectra from TRD digits found on tracks.
std::ostringstream debug
void findDigitsForTracklet(const Tracklet64 &trklt, const TriggerRecord &trig, int type)
Search for up to 3 neighbouring digits matching given tracklet and fill the PH values.
void setInput(const o2::globaltracking::RecoContainer &input, gsl::span< const Digit > *digits)
Initialize the input arrays.
void reset()
Reset the output.
void process()
Main processing function.
void init()
Initialize what is needed.
Header for data corresponding to the same hardware trigger adapted from DataFormatsITSMFT/ROFRecord.
int getNumberOfDigits() const
GLdouble GLdouble right
Definition glcorearb.h:4077
GLint GLint GLsizei GLint GLenum GLenum type
Definition glcorearb.h:275
constexpr int TIMEBINS
the number of time bins
Definition Constants.h:74
gsl::span< const o2::trd::TriggerRecord > getTRDTriggerRecords() const
gsl::span< const o2::trd::Tracklet64 > getTRDTracklets() const
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"
std::vector< Digit > digits