Project
Loading...
Searching...
No Matches
DigitsWriteoutBuffer.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
12#include <unordered_map>
13#include <vector>
14#include <list>
15#include <deque>
16#include <iostream>
17#include <gsl/span>
21#include "TMath.h"
22#include <fairlogger/Logger.h>
23
24using namespace o2::emcal;
25
26DigitsWriteoutBuffer::DigitsWriteoutBuffer(unsigned int nTimeBins) : mBufferSize(nTimeBins)
27{
28 for (int itime = 0; itime < nTimeBins; itime++) {
29 mTimedDigitsFuture.push_back(o2::emcal::DigitTimebin());
30 }
31}
32
34{
35 const SimParam* simParam = &(o2::emcal::SimParam::Instance());
36
37 mLiveTime = simParam->getLiveTime();
38 mBusyTime = simParam->getBusyTime();
39 mPreTriggerTime = simParam->getPreTriggerTime();
40 mSwapPhase = simParam->getBCPhaseSwap();
41 mDigitStream.init();
42}
43
45{
46 for (auto& iNode : mTimedDigitsFuture) {
47 iNode.mRecordMode = false;
48 iNode.mEndWindow = false;
49 iNode.mDigitMap->clear();
50 }
51 mTimedDigitsPast.clear();
52}
53
55{
56 if (mTimedDigitsFuture.size() < mBufferSize - 1) {
57 int originalSize = mTimedDigitsFuture.size();
58 for (int itime = 0; itime < (mBufferSize - originalSize); itime++) {
59 mTimedDigitsFuture.push_back(o2::emcal::DigitTimebin());
60 }
61 }
62}
63
64// Add digits to the buffer
65void DigitsWriteoutBuffer::addDigits(unsigned int towerID, std::vector<LabeledDigit>& digList)
66{
67
68 for (int ientry = 0; ientry < digList.size(); ientry++) {
69 auto& buffEntry = mTimedDigitsFuture[ientry];
70 auto& dig = digList.at(ientry);
71
72 auto towerEntry = buffEntry.mDigitMap->find(towerID);
73 if (towerEntry == buffEntry.mDigitMap->end()) {
74 towerEntry = buffEntry.mDigitMap->insert(std::pair<int, std::list<o2::emcal::LabeledDigit>>(towerID, std::list<o2::emcal::LabeledDigit>())).first;
75 }
76 towerEntry->second.push_back(dig);
77 }
78}
79
80// When the current time is forwarded (every 100 ns) the entry 0 of the future dequeue
81// is removed and pushed at the end of the past dequeue. At the same time a new entry in
82// the future dequeue is pushed at the end, and - in case the past dequeue reached 15 entries
83// the first entry of the past dequeue is removed.
85{
86
87 unsigned long eventTime = record.getTimeNS();
88
89 // To see how much the marker will forwarded, or see how much of the future buffer will be written into the past past buffer
90 int sampleDifference = (eventTime - mTriggerTime) / 100 - (mLastEventTime - mTriggerTime) / 100;
91
92 for (int idel = 0; idel < sampleDifference; idel++) {
93
94 // Stop reading if record mode is false to save memory
95 if (!mTimedDigitsFuture.front().mRecordMode) {
96 break;
97 }
98
99 // with sampleDifference, the future buffer will written into the past buffer
100 // the added entries will be removed the future, and the same number will added as empty bins
101 mTimedDigitsPast.push_back(mTimedDigitsFuture.front());
102 mTimedDigitsFuture.pop_front();
103 mTimedDigitsFuture.push_back(o2::emcal::DigitTimebin());
104
105 if (mTimedDigitsPast.size() > mBufferSize) {
106 mTimedDigitsPast.pop_front();
107 }
108
109 // If it is the end of the readout window write all the digits, labels, and trigger record into the streamer
110 if (mTimedDigitsPast.back().mEndWindow) {
111
112 // Find the trigger time bin
113 o2::emcal::DigitTimebin triggerNode;
114 for (auto& digitTimebin : mTimedDigitsPast) {
115 if (digitTimebin.mTriggerColl) {
116 triggerNode = digitTimebin;
117 break;
118 }
119 }
121 mDigitStream.fill(mTimedDigitsPast, triggerNode.mInterRecord.value());
122 clear();
123 }
124 }
125
126 // If we have a trigger, all the time bins in the future buffer will be set to record mode
127 // the last time bin will the end of the readout window since it will be mTriggerTime + 1500 ns
128 if (trigger && ((eventTime - mTriggerTime) >= (mLiveTime + mBusyTime) || mFirstEvent)) {
129 LOG(debug) << "Trigger received and accepted";
130 mTriggerTime = eventTime;
131 mTimedDigitsFuture.front().mTriggerColl = true;
132 mTimedDigitsFuture.front().mInterRecord = record;
133 mTimedDigitsFuture[(mLiveTime / 100) - 1].mEndWindow = true;
134
135 long timeStamp = (eventTime / 100) * 100;
136 for (auto& iNode : mTimedDigitsFuture) {
137 long diff = (timeStamp - eventTime);
138 if (TMath::Abs(diff) > mLiveTime) {
139 break;
140 }
141 iNode.mRecordMode = true;
142 timeStamp += 100;
143 }
144 }
145
146 // If we have a pre-trigger collision, all the time bins in the future buffer will be set to record mode
147 if ((eventTime - mTriggerTime) >= (mLiveTime + mBusyTime - mPreTriggerTime) || mFirstEvent) {
148 LOG(debug) << "Pre-trigger collision";
149 long timeStamp = (eventTime / 100) * 100;
150 for (auto& iNode : mTimedDigitsFuture) {
151 long diff = (timeStamp - eventTime);
152 if (TMath::Abs(diff) > mLiveTime) {
153 break;
154 }
155 iNode.mRecordMode = true;
156 timeStamp += 100;
157 }
158 }
159
160 mLastEventTime = eventTime;
161 // mPhase = ((int)(std::fmod(mLastEventTime, 100) / 25));
162 mPhase = (record.bc + mSwapPhase) % 4;
163
164 if (mFirstEvent) {
165 mFirstEvent = false;
166 }
167}
168
171{
172 for (unsigned int ibin = 0; ibin < mBufferSize; ibin++) {
173
174 if (!mTimedDigitsFuture.front().mRecordMode || mTimedDigitsFuture.front().mDigitMap->empty()) {
175 break;
176 }
177
178 mTimedDigitsPast.push_back(mTimedDigitsFuture.front());
179 mTimedDigitsFuture.pop_front();
180
181 if (mTimedDigitsPast.size() > mBufferSize) {
182 mTimedDigitsPast.pop_front();
183 }
184
185 if (mTimedDigitsPast.back().mEndWindow) {
186
187 // Find the trigger time bin
188 o2::emcal::DigitTimebin triggerNode;
189 for (auto& digitTimebin : mTimedDigitsPast) {
190 if (digitTimebin.mTriggerColl) {
191 triggerNode = digitTimebin;
192 break;
193 }
194 }
196 mDigitStream.fill(mTimedDigitsPast, triggerNode.mInterRecord.value());
197 clear();
198 break;
199 }
200 }
201}
202
204{
205
206 // Setting the digit time
207 // If we have a delay the first digit in the buffer will start from mDelay,
208 // If we also have digits coming from pre-trigger collisions, also their time will start from mDelay,
209 // so, to shift the digits back to zero, their time has to be subtracted by the extra digits (with time [0,mDelay])
210 int timeStamp = mLiveTime - (mTimedDigitsPast.size() * 100);
211 for (auto& buffEntry : mTimedDigitsPast) {
212 for (auto& [tower, digitList] : *buffEntry.mDigitMap) {
213 for (auto& digit : digitList) {
214 digit.setTimeStamp(digit.getTimeStamp() + timeStamp);
215 }
216 }
217 timeStamp += 100;
218 }
219}
std::ostringstream debug
void init()
Initialize the streamer.
void fill(std::deque< o2::emcal::DigitTimebin > &digitlist, o2::InteractionRecord record)
Fill all the containers, digits, labels, and trigger records.
DigitsWriteoutBuffer(unsigned int nTimeBins=15)
Default constructor.
void setSampledDigitsTime()
This function sets the right time for all digits in the buffer.
void finish()
This is for the readout window that was interrupted by the end of the run.
void reserve()
Reserve space for the future container.
void forwardMarker(o2::InteractionTimeRecord record, bool trigger)
forward the marker for every 100 ns
void addDigits(unsigned int towerID, std::vector< LabeledDigit > &digList)
EMCal simulation parameters.
Definition SimParam.h:28
Float_t getBusyTime() const
Definition SimParam.h:64
Float_t getLiveTime() const
Definition SimParam.h:63
Float_t getPreTriggerTime() const
Definition SimParam.h:65
Int_t getBCPhaseSwap() const
Definition SimParam.h:45
uint16_t bc
bunch crossing ID of interaction
double getTimeNS() const
get time in ns from orbit=0/bc=0
DigitTimebinBase templated, used for the DigitsWriteoutBuffer and DigitsWriteoutBufferTRU.
std::optional< o2::InteractionRecord > mInterRecord
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"